如何在Ruby中分离现有的类变量?

时间:2015-04-01 21:36:04

标签: ruby

我有一个现有的类层次结构,它使用了类变量和类实例变量。类变量在所有子类之间共享的事实是可取的,因为我有一些常见数据,但现在我需要在继承层次结构的其他分支之间拆分该共享数据。

这大致是它现在的样子和工作方式:

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

但我想修改Base1Base2(以及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现在是一个类变量Base1Base2类,无需在Base以外的地方定义。

2 个答案:

答案 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')