给定下面代码中的超类,我希望所有子类都有一些实例变量。
下面的代码做到了这一点,但未能为所有可能的子类正确初始化该变量。
我打开了超类的本征类。这是代码(也在Rubyfidle中):
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中,只有SomeSuperClass.variable
被初始化。我不知道如何为所有可能的子类初始化这个变量。有什么想法吗?
我发现的最好的解决方案是延迟初始化变量,覆盖访问器,如:
class SomeSuperClass
def self.variable
@variable ||= 'Hi'
end
end
动机:
我需要一个给定类的所有子类,让我们称之为Vigilant,能够监控在其直接子类上发生的一些事情。这些信息存储在类中,因此每个信息都有不同的状态。
我不能使用类变量,因为两个类a<B将修改相同的变量。我也不能直接访问子类,所以我需要一种方法来赋予Vigilant的所有子类存储和检索其子类信息的能力。
通过定义打开特征类的访问者,比如:
A.singleton_class.instance_eval { attr_accessor :x }
所有子类B class B < A; end
现在都可以执行B.x
,因为在其超类特征类中添加了一个方法(访问器),因此可以在查找中找到。
第一个例子表明B.x不同于A.x
现在,我真正不明白的是x在哪里;变量,而不是访问器。如果我执行B.instance_variables
,则显示[]
,与B.singleton_class.instance_variables 相同
我希望所有的子类在它们的单例类/本征类上都有一个变量。
对不起,这不是你在这里做的:
puts SomeSuperClass.variable # => 'This only works for the superclass'
puts SubClass.variable # => '
为什么你会认为写
SomeSuperClass.variable
相当于伪代码:
SomeSuperClassSingletonClass.variable
或真实代码:
SomeSuperClass.singleton_class.variable
一个类和它的singleton类是两个不同的类。
此外,此代码:
class << self
attr_accessor :variable
@variable = ': )' # This does't seem to have any effect
end
不会为@变量创建访问器,与此代码相同:
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无关,该变量是在所有def之外定义的@变量被查找(或设置)在那个时刻的任何对象上。唯一可以调用这些def的对象是Dog类的实例,因此x将在Dog实例上查找(或设置),而不是Dog类。
还要注意,当执行@x = 'hello'
行时,self等于Dog类,因此@x将自己附加到Dog类。
我认为您没有在singleton类上设置实例变量的用例。以下是你想要做的事情:
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
的用例,让我们听听。