2009-05-27 8 views
2
class Object 
    attr_reader :foo 
    def initialize 
    @foo = 'bar' 
    end 
end 

Object.new.foo # => 'bar' 
''.foo # => nil 
//.foo # => nil 
[].foo # => nil 

Ich möchte, dass sie alle 'bar'In Ruby, wie kann ich Instanzvariablen in neue Objekte von Core-Klassen initialisieren von Literalen erstellt

Am bewusst zurück, dass Sie dies bereits tun können:

class Object 
    def foo 
    'bar' 
    end 
end 

Aber ich möchte speziell eine Statusvariable initialisieren. Beachten Sie auch, dass dies nicht funktioniert.

class String 
    alias_method :old_init, :initialize 
    def initialize(*args) 
    super 
    old_init(*args) 
    end 
end 

class Object 
    attr_reader :foo 
    def initialize 
    @foo = 'bar' 
    super 
    end 
end 

''.foo # => nil 

auch nicht dies:

class String 
    attr_reader :foo 
    def initialize 
    @foo = 'bar' 
    end 
end 

''.instance_variables # => [] 

Ich bin zu denken beginnen, dass dies nicht wirklich möglich ist.

+1

Der Grund, warum dies für Sie nicht funktioniert, ist, dass all diese anderen Klassen, die von Objekt erben, 'initialize' außer Kraft setzen und nicht die Superklassenversion davon aufrufen. – rampion

+0

Hat meinen Beitrag bearbeitet. –

Antwort

0

Es ist nicht eine Instanz-Variable, sondern die Anforderungen Ihres Beispiel

class Object 
    def foo 
    'bar' 
    end 
end 
4

Wenn das Ding Sie versuchen zurückzukehren (hier 'bar') erfordert viel mehr Rüstkosten als ein kleiner String entspricht, können Sie verwenden Sie die memoized Version von HermanD's answer könnte:

class Object 
    def foo 
    @foo ||= begin 
     'bar' # something far more complicated than just "'bar'" 
    end 
    end 
end 

Sie sogar die memoization für billige Sachen wie Strings verwenden können, wenn Sie wirklich die Instanz-Variable müssen eingestellt werden (für einige reaso n, die ich bei ihnen Moment nicht ganz glauben kann):

class Object 
    def foo 
    @foo ||= 'bar' 
    end 
end 
+1

+1, aber das funktioniert nicht, wenn Sie instance_variable_get aufrufen, bevor Sie den Accessor verwenden. Es ist interessant, dass Sie sich nicht auf Objects # initialize verlassen können. –

+0

Junge, das ist ein ziemlich peinlicher Fall, aber ich habe _no_ _doubt_, dass irgendeine obskure Bibliothek in das hineinrufen wird und es wird explodieren und du wirst gehen, "WTF?" –

5

Diese ist möglich.

class Object 
    class << self 
    Kernel.send :define_method, :foo do #Object.send to be more restrictive 
     @foo = 'bar' 
    end 
    end 
end 

.

irb(main):023:0> class Object 
irb(main):024:1> class << self 
irb(main):025:2> Kernel.send :define_method, :foo do 
irb(main):026:3* @foo = 'bar' 
irb(main):027:3> end 
irb(main):028:2> end 
irb(main):029:1> end 
=> #<Proc:[email protected](irb):25> 
irb(main):030:0> x = Object.new 
=> #<Object:0x7f5ac89d6348> 
irb(main):031:0> x.foo 
=> "bar" 
irb(main):032:0> [].foo 
=> "bar" 
irb(main):033:0> //.foo 
=> "bar" 

Es ist wichtig, Eigenklassen zu verstehen. Jede Klasse wird auf mysteriöse Weise von der Ruby-Interpreter als eine versteckte Klasse Typ implementiert:

irb(main):001:0> class Object 
irb(main):002:1> def eigenclass 
irb(main):003:2>  class << self; self; end 
irb(main):004:2> end 
irb(main):005:1> end 
=> nil 
irb(main):006:0> x = Object.new 
=> #<Object:0x7fb6f285cd10> 
irb(main):007:0> x.eigenclass 
=> #<Class:#<Object:0x7fb6f285cd10>> 
irb(main):008:0> Object.eigenclass 
=> #<Class:Object> 
irb(main):009:0> Object.class 
=> Class 

Also, in Ihrem Beispiel, wenn Sie versuchen, foo auf Ihre Objekte zu nennen, es #<Object:0x7fb6f285cd10> auf der Klasse arbeitet. Was Sie jedoch wollen, ist die Geheimklasse #<Class:#<Object:0x7fb6f285cd10>>

Ich hoffe, das hilft!

Verwandte Themen