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

私はこの状況が多いです。たとえば、私のアプリには約 40 のIdenticalDescendentクラスがあります。私はこのパターンが気に入っています。これにより、A::IdenticalDescendentorまたは what を呼び出して、さまざまなドメイン ( orB::IdenticalDescendentで指定) の特定の関連する動作にアクセスできます。理由により、動作クラスタリングを再設計しても問題を完全に抽象化することはできません。AB

したがって、私の質問の一般的な形式は、これらすべてで IdenticalDescendent の生成を自動化するにはどうすればよいかということです。CommonParentこのパターンを呼び出さない子孫が存在するため、アクションはおそらくそこで発生しないはずです。ミックスインか何かで発生するはずだと思いますが、やろうとすると次のようになります。

class A < CommonParent
  include CommonBehaviour

  ... some code ...
end

module CommonBehaviour
  ... what ...
end

CommonBehaviourIdenticalDescendent が包含クラスから派生できるようにするための書き方がわかりません。

StackOverflow を助けてください。あなただけが私の希望です。

4

3 に答える 3

1

私が探していた答えは、コールバックClass.new内でブロック表記を使用することです。self.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トリガーinheritedされklass => Descendent、 の匿名サブクラスDescendentが作成されるなどして、「スタック レベルが深すぎる例外」が発生します。

于 2015-06-26T18:55:52.443 に答える