鉴于下面代码中的超类,我希望所有子类都有一些实例变量。
下面的代码可以做到这一点,但无法为所有可能的子类正确初始化该变量。
我打开了我的超类的本征类。这是代码(也在rubyfiddle中):
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'
我想初始化所有可能的sublcasses。在前两次放置中,仅初始化SomeSuperClass.variable
。我不知道如何为所有可能的子类初始化此变量。有什么想法吗?
我找到的最佳解决方案是延迟初始化变量,覆盖访问器,如:
class SomeSuperClass
def self.variable
@variable ||= 'Hi'
end
end
动机:
我需要给定类的所有子类,让我们称它为Vigilant,能够监视其直接子类上发生的一些事情。此信息存储在类中,因此每个信息具有不同的状态。
我不能使用类变量,因为两个类A&lt; 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相同
答案 0 :(得分:2)
我希望所有子类在其singleton类/ eigenclass上都有一个变量。
对不起,这不是你在这里做的事情:
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无关,它是在所有defs之外定义的。 @variables被查找(或设置)在该瞬间的任何自身对象上。可以调用那些defs的唯一对象是类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
的用例,那就听听吧。