1

我有以下情况:

class A < CommonParent
  ... some code ...

  class IdenticalDescendent < self
    identical_statement_0
    identical_statement_1
  end
end

class B < CommonParent
  ... some other code ...

  class IdenticalDescendent < self
    identical_statement_0
    identical_statement_1
  end
end

这种情况我很多。就像,我的应用程序中有大约 40IdenticalDescendent个课程。我喜欢这种模式,它允许我调用A::IdenticalDescendentorB::IdenticalDescendent或访问不同域中的某些相关行为(由Aor指定B)。出于某种原因,我不能通过重新设计行为聚类来完全抽象出问题。

所以我的问题的一般形式是如何在所有这些中自动生成 IdenticalDescendent。有其后代CommonParent不调用此模式,因此该操作可能不应该在那里发生。我想它应该发生在 mixin 或其他东西中,但我发现如果我只是尝试这样做:

class A < CommonParent
  include CommonBehaviour

  ... some code ...
end

module CommonBehaviour
  ... what ...
end

我不知道如何编写CommonBehaviour以允许 IdenticalDescendent 从包含类下降。

帮助我 StackOverflow,你是我唯一的希望。

4

3 回答 3

1

我一直在寻找的答案是Class.newself.included回调中使用块表示法。我现在有这个:

module CommonDescendant
  def self.included(base)
    descendant_class = Class.new(base) do
      ... put my desired common behavior here ...
    end

    base.const_set :Descendant, descendant_class
  end
end

class A
  include CommonDescendant

  ... unique behavior ...
end

class B
  include CommonDescendant

  ... unique other behavior ...
end

这给了我们我想要的设计!

于 2015-06-26T09:14:49.117 回答
0

我相信您可以通过使用回调(挂钩)Class#inherited来自动化您的模式:

class CommonParent
  def self.inherited(klass)
    return unless klass.superclass == CommonParent
    klass.const_set(:Descendent, Class.new(klass) do
      def x
        puts "in x"
      end
    end)
  end
end

class A < CommonParent
  def a
    puts "in a"
  end   
end

d = A::Descendent.new #=> #<A::Descendent:0x007f99620172e8> 
d.a                   #   in a
d.x                   #   in x

class B < CommonParent
  def b
    puts "in b"
  end
end

d = B::Descendent.new #=> #<B::Descendent:0x007f99618b18f0> 
d.b                   #   in b
d.x                   #   in x
d.a                   #=> NoMethodError:... (as expected)

请注意,没有:

return unless klass.superclass == CommonParent

的创建A::Descendent将触发inheritedklass => Descendent导致创建匿名子类Descendent等,从而导致“堆栈级别太深异常”。

于 2015-06-26T18:55:52.443 回答
-1

我建议将后代类和方法生成分开。当然,你可以把所有东西都扔进一个class_eval街区(这肯定会很臭)。

类似于以下内容(完全未经测试)

module CommonDescendants
  Descendant = Class.new(self) do 
    include CommonDescendantMethods
  end
end

module CommonDescendantMethods
end

class A < CommonParent
  extend CommonDescendants
end
于 2015-06-26T07:06:57.763 回答