在Ruby中,如何在从文字创建的核心类的新对象中初始化实例变量

时间:2009-05-27 09:26:29

标签: ruby oop

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

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

我希望他们全部返回'bar'

我知道你已经可以这样做了:

class Object
  def foo
    'bar'
  end
end

但我特别想初始化一个状态变量。另请注意,这不起作用。

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

这也不是:

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

''.instance_variables # => []

我开始认为这实际上是不可能的。

3 个答案:

答案 0 :(得分:5)

可能。

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:0x00007f5ac89db168@(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"

理解本征类非常重要。每个类都由Ruby解释器神秘地实现为隐藏的类类型:

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

因此,在您的示例中,当您尝试在对象上调用foo时,它将在类#<Object:0x7fb6f285cd10>上运行。但是,您希望它操作的是秘密类#<Class:#<Object:0x7fb6f285cd10>>

我希望这有帮助!

答案 1 :(得分:4)

如果您尝试返回的内容(此处为'bar')需要的设置成本远远低于小型字符串,则可以使用HermanD's answer的备忘版本:

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

如果真的需要设置实例变量,你甚至可以使用memoization来处理像Strings这样的便宜的东西(由于某些原因我不能在他们的时刻想到):

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

答案 2 :(得分:0)

它不是实例变量,但会满足您的示例

的要求
class Object
  def foo
    'bar'
  end
end