1

鉴于下面代码中的超类,我希望所有子类都有一些实例变量。

下面的代码做到了这一点,但未能为所有可能的子类正确初始化该变量。

我打开了我的超类的特征类。这是代码(也在ruby​​fiddle中):

class SomeSuperClass
  class << self
    attr_accessor :variable
    @variable = ': )' # This does't seem to have any effect
  end
  self.variable = 'This only works for the superclass'
end

class SubClass < SomeSuperClass; end

puts SomeSuperClass.variable # => 'This only works for the superclass'
puts SubClass.variable # => ''

SomeSuperClass.variable = 'I am the superclass'
SubClass.variable = 'I am the subclass'

puts SomeSuperClass.variable # => 'I am the superclass'
puts SubClass.variable # => 'I am the subclass'

我想初始化所有可能的子类。在前两个 put 上,onlySomeSuperClass.variable被初始化。我不知道如何为所有可能的子类初始化这个变量。有任何想法吗?

我发现的最佳解决方案是延迟初始化变量,覆盖访问器,如下所示:

class SomeSuperClass
  def self.variable
    @variable ||= 'Hi'
  end
end

动机:

我需要给定类的所有子类,我们称之为 Vigilant,能够监视其直接子类上发生的一些事情。此信息存储在类中,因此每个类都有不同的状态。

我不能使用类变量,因为两个类 A < B 将修改同一个变量。我也不能直接访问子类,所以我需要一种方法来为 Vigilant 的所有子类提供存储和检索有关其子类的信息的能力。

通过定义打开 eigen 类的访问器,可以说:

A.singleton_class.instance_eval { attr_accessor :x }

现在所有子类 Bclass B < A; end都可以这样做B.x,因为方法(访问器)已添加到其超类 eigen 类中,因此可以在查找中找到。

第一个例子表明 Bx 与 Ax 不同

现在,我真的不明白 x 在哪里;变量,而不是访问器。如果我这样做,B.instance_variables[]与 B.singleton_class.instance_variables 相同

4

1 回答 1

2

我希望所有子类在它们的单例类/特征类上都有一个变量。

对不起,这不是你在这里做的:

puts SomeSuperClass.variable # => 'This only works for the superclass'
puts SubClass.variable # => '

为什么你会认为写作

SomeSuperClass.variable 

相当于伪代码:

SomeSuperClassSingletonClass.variable

或真正的代码:

SomeSuperClass.singleton_class.variable

一个类和它的单例类是两个不同的类。

另外,这段代码:

  class << self
    attr_accessor :variable
    @variable = ': )' # This does't seem to have any effect   
  end

不会为该@variable 创建访问器,与以下代码相同:

class Dog
  attr_accessor :x

  @x = 'hello'
end

puts Dog.x

...不为该 @x 变量创建访问器:

--output:--
undefined method `x' for Dog:Class (NoMethodError) 

attr_accessor() 的作用是:

class Dog
  def x
    @x
  end

  def x=(val)
    @x = val
  end

  #=====

  @x = 'hello'
end

这些方法与在所有定义之外定义的类实例变量@x无关。@variables 在那一刻在任何对象上查找(或设置)自我。唯一可以调用这些定义的对象是 Dog 类的实例,因此 x 将在 Dog 实例而不是 Dog 类上查找(或设置)。

另请注意,当行@x = 'hello'执行时,self 等于 Dog 类,因此 @x 将自身附加到 Dog 类。

我认为您没有在单例类上设置实例变量的用例。这似乎是您正在尝试做的事情:

class SomeSuperClass
  class << self
    attr_accessor :variable
  end

  self.variable = 'hello'

  def self.inherited(subclass)
    subclass.singleton_class.instance_eval do
      attr_accessor :variable
    end

    subclass.variable = "Hi"
  end

end

class SubClass < SomeSuperClass
end

puts SomeSuperClass.variable
puts SubClass.variable


--output:--
hello
Hi

该代码创建了所谓的class instance variables. 如果您认为您有 的用例singleton class instance variables,让我们来听听。

于 2014-10-03T04:52:53.993 回答