【问题标题】:What is the correct way to encapsulate factory methods from derived classes when implementing factory in base class?在基类中实现工厂时,从派生类中封装工厂方法的正确方法是什么?
【发布时间】:2019-03-27 16:14:00
【问题描述】:

我正在尝试创建能够注册派生类以从基类创建的简单类。但是我找不到从后代中封装此功能的好方法。

类变量对我来说是个坏主意,因为它们在继承链中无处不在。所以我尝试对类实例变量做一些事情。完美的是,除了 register_as 之外,所有类方法都将不可访问

class A
  @registered = {}
  class << self
    def register_as(name)
      A.registered[name] = self
    end

    def known
      A.registered
    end

    protected
    attr_accessor :registered
  end

  def helpful_method
  end

end

class B < A
  class << self
    def reg_trash
      A.registered[:trash] = :trash
    end
  end
  B.register_as :b
end

B.reg_trash
p A.known

但是注册仍然可以从 B 类访问。 目前看起来唯一可能的选择是将 A 类拆分为专用的 Factory 类,并且 A 类将只包含有用的实例方法。 也许可以通过 .inherited 和 .undef_method 做一些事情,不是吗?

【问题讨论】:

    标签: ruby inheritance factory class-method


    【解决方案1】:

    也许可以通过 .inherited 和 .undef_method 做一些事情,不是吗?

    是的,这是可能的。但对我来说,这个想法很臭 - 你会破坏可替代性。

    如果您不希望“派生”类继承父类的行为,那为什么还要使用继承呢?尝试组合并仅混合您需要的行为。例如,这样的事情可以工作(非常肮脏的例子,但我希望你明白了):

    class A
      module Registry
        def register_as(name)
          A.register_as(name, self)
        end
      end
    
      @registered = {}
    
      def self.register_as(name, klass)
        @registered[name] = klass
      end
    
      def self.known
        @registered
      end
    end
    
    class B
      extend A::Registry
      register_as :b  
    end
    
    class C
      extend A::Registry
      register_as :c
    end
    
    A.known # => {:b => B, :c => C}
    

    【讨论】:

    • OP 应该阅读 Liskov 替换原则。如果在使用A 的任何地方都使用B 没有意义,那么您不应该写class B &lt; A
    • @Max 我没听懂。我不想打破 A 类和 B 类实例的 Liskov 替换原则,我只是想修改 B 类的单例类和 A 类的单例类之间的关系行为,这对于第一个类来说是超级的。我同意最好的方法是使用组合而不是继承。我对其他可能的解决方案很感兴趣,因为我是 Ruby 世界的新手。
    • “我找不到从后代封装此功能的好方法。”如果您希望能够调用A.registered 但不能调用B.registered,那么由于LSP,您不能拥有class B &lt; A。您必须始终能够将B 放在有A 的任何位置。 Ruby 的对象模型是专门为支持这一点而设计的。
    猜你喜欢
    • 2016-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多