我有一个现有的类层次结构,它使用了类变量和类实例变量。类变量在所有子类之间共享的事实是可取的,因为我有一些常见数据,但现在我需要在继承层次结构的其他分支之间拆分该共享数据。
这大致是它现在的样子和工作方式:
class Base
@@common = ''
@per_child = ''
def self.show
"base: #{@@common}; me: #{@per_child}"
end
def self.set(val)
@per_child = val
end
def self.set_all(val)
@@common = val
end
end
class Child1 < Base; set "first child"; end
class Child2 < Base; set "second child"; end
Base.set_all('core')
puts "[Child1] #{Child1.show}"
puts "[Child2] #{Child2.show}"
输出:
[Child1] base: core; me: first child
[Child2] base: core; me: second child
这正是我想要的东西。现在,我试图复制Base
类的行为,而不重复代码。如下所示:
# Same "Base" class as above
class Base1 < Base; end
class Base2 < Base; end
class Child1 < Base1; set "first child"; end
class Child2 < Base1; set "second child"; end
class Child3 < Base2; set "third child"; end
class Child4 < Base2; set "fourth child"; end
Base1.set_all('first base')
Base2.set_all('second base')
puts "[Child1] #{Child1.show}"
puts "[Child2] #{Child2.show}"
puts "[Child3] #{Child3.show}"
puts "[Child4] #{Child4.show}"
显然上面的输出是:
[Child1] base: second base; me: first child
[Child2] base: second base; me: second child
[Child3] base: second base; me: third child
[Child4] base: second base; me: fourth child
但我想修改Base1
和Base2
(以及Base
的定义,如果需要),以便输出为:
[Child1] base: first base; me: first child
[Child2] base: first base; me: second child
[Child3] base: second base; me: third child
[Child4] base: second base; me: fourth child
我理解为什么它的行为方式如此,但我不确定如何获得我正在寻找的行为,@@common
现在是一个类变量Base1
和Base2
类,无需在Base
以外的地方定义。
答案 0 :(得分:1)
根据我的第一个答案的反馈,这是第二次拍摄。这抽象了类变量层次结构行为。我希望它在某种程度上有所帮助。
module BaseBehavior
def self.included(base)
base.send(:extend, ClassMethods)
end
module ClassMethods
def set_all(val)
self.send :class_variable_set, class_var_name, val
end
def class_var_name
"@@#{self.name}_base_var"
end
def class_var
if class_variable_defined? class_var_name
self.send :class_variable_get, class_var_name
else
superclass.class_var
end
end
def show
"base: #{class_var}; me: #{@per_child}"
end
end
end
class Base
include BaseBehavior
set_all 'core'
@per_child = ''
def self.set(val)
@per_child = val
end
end
class Base1 < Base
include BaseBehavior
set_all 'first base'
end
class Base2 < Base
include BaseBehavior
set_all 'second base'
end
class Child1 < Base1; set "first child"; end
class Child2 < Base1; set "second child"; end
class Child3 < Base2; set "third child"; end
class Child4 < Base2; set "fourth child"; end
puts "[Child1] #{Child1.show}"
puts "[Child2] #{Child2.show}"
puts "[Child3] #{Child3.show}"
puts "[Child4] #{Child4.show}"
答案 1 :(得分:0)
我认为使用合成而不是继承会更好。这意味着设置明确地相互通信的对象,而不是使用父子类关系。依赖继承通常会导致您在此处遇到的状态管理问题,而组合可以更好地控制对象之间的状态管理方式。
例如:
Class Node
attr_accessor :parent, :name
def initialize(parent, name)
@parent = parent
@name = name
end
def show
"base: #{parent.name} child: #{name}"
end
end
parent = Node.new(nil, 'core')
child1 = Node.new(parent, 'child1')
child2 = Node.new(parent, 'child2')