PythonのMixinモードについて考える

3995 ワード

CやC++のような言語では多重継承がサポートされており、1つのサブクラスに複数の親がいるという設計が非難されることが多い.継承は「is-a」関係であるべきだからだ.例えば、乗用車類は交通機関類を継承する.乗用車は(「is-a」)交通機関であるからだ.一つのものが多様なものであるはずがないので、多重継承は存在してはいけない.しかし、このような場合、1つのクラスは確かに複数のクラスを継承する必要がありますか?
答えはあります.私たちはやはり交通手段を例に挙げます.民間航空機は交通手段であり、土豪たちにとってヘリコプターも交通手段です.この2つの交通手段には、飛行する機能がありますが、乗用車にはありません.だから、私たちは飛行機能を交通機関という親に書くことはできません.しかし、民間航空機とヘリコプターがそれぞれ自分の飛行方法を書いている場合、コードをできるだけ再利用する原則に反している(今後、飛行ツールが多くなれば、多くの重複コードが現れる).どうすれば、この2つの飛行機に交通手段と飛行機の2つの親を同時に継承させるしかなく、多重継承が現れた.この時、継承は「is-a」関係でなければならないことに背いた.この難題はどうやって解決すればいいですか.
異なる言語は異なる方法を提供しています.まずJavaを見てみましょう.Javaはインタフェースinterface機能を提供し、多重継承を実現します.
public abstract class Vehicle {
}

public interface Flyable {
    public void fly();
}

public class FlyableImpl implements Flyable {
    public void fly() {
        System.out.println("I am flying");
    }
} 

public class Airplane extends Vehicle implements Flyable {
    private flyable;

    public Airplane() {
        flyable = new FlyableImpl();
    }

    public void fly() {
        flyable.fly();
    }
}

現在、私たちの飛行機は交通機関と飛行機の2つの属性を同時に持っており、飛行機の中の飛行方法を書き換える必要はありません.同時に、単一継承の原則を破壊していません.飛行機は交通手段であり、飛行可能な能力は飛行機の属性であり、インタフェースを継承することによって取得される.
トピックに戻ると、Python言語にはインタフェース機能はありませんが、多重継承できます.Pythonは多重継承で実現すべきではないでしょうか.はい、そうではありません.文法的に見ると、確かに多重継承によって実現されているからだ.いいえ、その継承は依然として「is-a」関係を守っているので、意味的には単一継承の原則に従っています.これはどのように理解しますか?例を見てみましょう.
class Vehicle(object):
    pass

class PlaneMixin(object):
    def fly(self):
        print 'I am flying'

class Airplane(Vehicle, PlaneMixin):
    pass

上のAirplaneクラスはマルチ継承を実現していることがわかりますが、その継承の2番目のクラスはPlaneではなくPlaneMixinと名付けられています.これは機能に影響しませんが、後でコードを読む人に教えてあげます.このクラスはMixinクラスです.だから意味から理解すると、AirplaneはVehicleであり、Planeではない.このMixinは、親としてではなく、機能としてサブクラスに追加されたことを他の人に伝え、Javaのインタフェースとして機能していることを示しています.
Mixinクラスを使用した多重継承には注意が必要です
  • まず、JavaのRunnable、Callableなどの
  • のように、あるアイテムではなく、ある機能を表す必要があります.
  • 次に単一の責任を負わなければなりません.複数の機能がある場合は、複数のMixinクラス
  • と書きます.
  • その後、サブクラスの実装
  • に依存しない
  • 最後に、サブクラスはこのMixinクラスを継承していなくても、ある機能が欠けていることができます.(例えば飛行機でも客を乗せることができますが、飛べません^^)