1. ホーム
  2. ruby

[解決済み] Rubyの継承とミキシンの比較

2022-07-08 14:59:13

質問

Rubyでは、複数のmixinを含めることができますが、1つのクラスしか拡張できないので、継承よりもmixinの方が好ましいと思われます。

質問: もしあなたが、拡張されたりインクルードされたりしなければ有用にならないコードを書いているなら、なぜそれをクラスにするのでしょうか? あるいは別の言い方をすれば、なぜ常にモジュールにしないのでしょうか?

クラスを必要とする理由はただ一つ、クラスをインスタンス化する必要がある場合だけです。しかし、ActiveRecord::Baseの場合、直接インスタンスを作成することはありません。ですから、代わりにモジュールにするべきではなかったでしょうか?

どのように解決するのですか?

I ちょうど でこのトピックについて読みました。 総合的なRubyist (ちなみに素晴らしい本です)。著者が私よりも上手に説明してくれているので、引用します。



単一のルールや公式が常に正しいデザインになることはありません。しかし、クラス対モジュールの決定をする際に、以下のことを念頭に置いておくと便利です。 クラス対モジュールの決定をするときに、2つの考慮事項を心に留めておくことは有用です。

  • モジュールはインスタンスを持ちません。 エンティティやモノは一般的にクラスでモデル化するのが最も良いということになります。 クラスでモデル化され、エンティティやモノの特性やプロパティは モジュールでカプセル化するのが最善です。これに対応して、4.1.1節で述べたように、クラス のように、クラス名は名詞になりがちですが、モジュール名は形容詞になることが多いようです (Stack 対Stacklike)。

  • クラスは1つのスーパークラスしか持つことができませんが、望むだけ多くのモジュールを混ぜることができます。 もし 継承を使用する場合は、スーパークラスとサブクラスの関係を適切にすることを優先してください。 の関係作りを優先してください。クラスの唯一無二のスーパークラス関係を使い果たさないようにしましょう。 クラスの唯一無二のスーパークラスの関係を、いくつかの特性のうちの 1 つであることが判明するようなものをクラスに与えるために使用しないでください。

これらのルールを1つの例でまとめると、やってはいけないことは次のようになります。

module Vehicle 
... 
class SelfPropelling 
... 
class Truck < SelfPropelling 
  include Vehicle 
... 

むしろ、こうしてください。

module SelfPropelling 
... 
class Vehicle 
  include SelfPropelling 
... 
class Truck < Vehicle 
... 

2番目のバージョンでは、実体とプロパティをよりきちんとモデル化しています。Truck は Vehicle の子孫であり(これは理にかなっています)、一方 SelfPropelling は乗り物(少なくとも、この世界のモデルで気になるものすべて)の特性であり、その特性は Truck が子孫、または特化した形であることによってトラックに受け継がれます。 の子孫、または特殊化された形態であることによって、トラックに受け継がれる特性です。