オブジェクト指向プログラミングにおいて、継承とは、オブジェクトまたはクラスを別のオブジェクト (プロトタイプベースの継承) またはクラス (クラスベースの継承) に基づいて作成し、同様の実装を保持するメカニズムです。また、スーパークラスや基底クラスなどの既存のクラスから新しいクラス (サブクラス) を派生させ、それらをクラスの階層に形成することとも定義されます。C ++などのほとんどのクラスベースのオブジェクト指向言語では、継承によって作成されたオブジェクト (「子オブジェクト」) は、基底クラスのコンストラクタ、デストラクタ、オーバーロードされた演算子、フレンド関数を除いて、「親オブジェクト」のすべてのプロパティと動作を取得します。継承により、プログラマは既存のクラスに基づいてクラスを作成したり、[1]同じ動作を維持しながら新しい実装を指定したり (インターフェイスを実現)、コードを再利用したり、パブリッククラスとインターフェイスを介して元のソフトウェアを個別に拡張したりすることができます。継承によるオブジェクトまたはクラスの関係は、有向非巡回グラフを生み出します。
継承されたクラスは、その親クラスまたはスーパークラスのサブクラスと呼ばれます。継承という用語は、クラスベースプログラミングとプロトタイプベースプログラミングの両方で広く使用されていますが、狭義では、クラスベースプログラミング(1つのクラスが別のクラスから継承する)にのみ使用されます。プロトタイプベースプログラミングの対応する手法は、代わりに委任(1つのオブジェクトが別のオブジェクトに委任する)と呼ばれます。クラスを変更する継承パターンは、言語間の互換性が維持されるように、単純なネットワークインターフェイスパラメータに従って事前に定義できます。[2] [3]
継承をサブタイピングと混同してはならない。[4] [5]言語によっては継承とサブタイピングが一致するものもあるが[a]、異なるものもある。一般に、サブタイピングはis-a関係を確立するのに対し、継承は実装を再利用するだけで、構文関係を確立するが、必ずしも意味関係を確立するわけではない(継承では動作のサブタイピングは保証されない)。これらの概念を区別するために、サブタイピングはインターフェース継承と呼ばれることもある(型変数の特殊化によってもサブタイピング関係が誘導されることは認めない)。一方、ここで定義される継承は実装継承またはコード継承と呼ばれる。[6]それでも、継承はサブタイプ関係を確立するためによく使用されるメカニズムである。[7]
継承は、オブジェクトの構成とは対照的です。オブジェクトの構成では、1 つのオブジェクトが別のオブジェクトを含みます(または、1 つのクラスのオブジェクトが別のクラスのオブジェクトを含みます) 。継承よりも構成を参照してください。サブタイプのis-a関係とは対照的に、構成はhas-a関係を実装します。
数学的に言えば、あらゆるクラス システムにおける継承は、そのシステム内のクラス セットに 厳密な半順序を誘導します。
歴史
1966 年、Tony Hoare はレコードについて、特にレコード サブクラスというアイデアについて発表しました。レコード サブクラスとは、共通のプロパティを持ちながらもバリアント タグで区別され、バリアント専用のフィールドを持つレコード型です。[8]これに影響を受けて、1967 年にOle-Johan DahlとKristen Nygaard は、異なるクラスに属しながらも共通のプロパティを持つオブジェクトを指定できる設計を発表しました。共通のプロパティはスーパークラスに集められ、各スーパークラス自体がスーパークラスを持つ可能性があります。したがって、サブクラスの値は複合オブジェクトであり、さまざまなスーパークラスに属するプレフィックス部分と、サブクラスに属するメイン部分で構成されます。これらの部分はすべて連結されます。[ 9 ]複合オブジェクトの属性には、ドット表記法でアクセスできます。このアイデアは、最初に Simula 67 プログラミング言語で採用されました。[ 10 ]
種類


継承にはパラダイムと特定の言語に基づいた様々な種類があります。[11]
- 単一継承
- サブクラスは 1 つのスーパークラスの機能を継承します。クラスは別のクラスのプロパティを取得します。
- 多重継承
- 1 つのクラスが複数のスーパークラスを持ち、すべての親クラスから機能を継承することができます。
「多重継承は 、効率的に実装するのが非常に難しいと広く考えられていました。たとえば、Objective Cに関する著書の C++ の概要で、Brad Cox は実際に、C++ に多重継承を追加することは不可能であると主張しました。したがって、多重継承はより困難なものに思えました。私は 1982 年にはすでに多重継承を検討しており、1984 年にシンプルで効率的な実装手法を見つけたため、この挑戦に抵抗できませんでした。これは、流行がイベントの順序に影響を与えた唯一のケースだと思います。」[12]
- 多階層継承
- サブクラスが別のサブクラスから継承されます。図「多段階継承」に示すように、クラスが別の派生クラスから派生することは珍しくありません。

多階層継承 - クラスAは派生クラスBの基底クラスとして機能し、派生クラス B は派生クラスCの基底クラスとして機能します。クラスBはAとCの間の継承のリンクを提供するため、中間基底クラスと呼ばれます。チェーンABC は継承パスと呼ばれます。
- 複数レベルの継承を持つ派生クラスは次のように宣言されます。
// C++ 言語実装 class A { ... }; // 基本クラスclass B : public A { ... }; // B は A から派生class C : public B { ... }; // C は B から派生
- このプロセスは任意のレベルに拡張できます。
- 階層的継承
- これは、1 つのクラスが複数のサブクラスのスーパークラス (基本クラス) として機能する場合です。たとえば、親クラス A には、サブクラス B と C の 2 つが存在する場合があります。B と C の親クラスはどちらも A ですが、B と C は 2 つの別々のサブクラスです。
- ハイブリッド継承
- ハイブリッド継承とは、上記の継承の 2 種類以上が混在する場合です。この例としては、クラス A にサブクラス B があり、サブクラス B に 2 つのサブクラス C と D がある場合が挙げられます。これは、マルチレベル継承と階層継承の両方が混在した状態です。
サブクラスとスーパークラス
サブクラス、派生クラス、継承クラス、または子クラスは、 1 つ以上の他のクラス (スーパークラス、基本クラス、または親クラスと呼ばれる) から 1 つ以上の言語エンティティを継承するモジュール式の派生クラスです。クラス継承のセマンティクスは言語によって異なりますが、一般的にサブクラスはスーパークラスのインスタンス変数とメンバー関数を自動的に継承します。
派生クラスを定義する一般的な形式は次の通りである: [13]
class SubClass : visibility SuperClass { // サブクラスのメンバー};
- コロンは、サブクラスがスーパークラスから継承することを示します。可視性はオプションであり、存在する場合は、privateまたはpublic のいずれかになります。デフォルトの可視性はprivateです。可視性は、基本クラスの機能がプライベートに派生されるか、パブリックに派生されるかを指定します。
一部の言語では、他の構成要素の継承もサポートされています。たとえば、Eiffelでは、クラスの仕様を定義する契約も継承クラスによって継承されます。スーパークラスは共通のインターフェイスと基本機能を確立し、特殊化されたサブクラスはこれを継承、変更、および補足できます。サブクラスによって継承されたソフトウェアは、サブクラスで再利用されているとみなされます。クラスのインスタンスへの参照は、実際にはそのサブクラスの 1 つを参照している可能性があります。参照されているオブジェクトの実際のクラスは、コンパイル時に予測できません。統一されたインターフェイスを使用して、さまざまなクラスのオブジェクトのメンバー関数を呼び出します。サブクラスは、スーパークラスの関数を、同じメソッド シグネチャを共有するまったく新しい関数に置き換えることができます。
サブクラス化できないクラス
一部の言語では、クラス宣言に特定のクラス修飾子を追加することで、クラスをサブクラス化不可として宣言できます。例としては、 JavaおよびC++11以降finalの キーワードや、 C# の キーワードなどがあります。このような修飾子は、 キーワードおよびクラス識別子宣言の前に、クラス宣言に追加されます。このようなサブクラス化不可のクラスは、特に開発者がソース コードではなくコンパイル済みバイナリにしかアクセスできない場合に、再利用性を制限します。
sealedclass
サブクラス化できないクラスにはサブクラスがないため、そのクラスのオブジェクトへの参照またはポインターが実際にはそのクラスのインスタンスを参照しており、サブクラスのインスタンス (存在しない) やスーパークラスのインスタンス (参照型のアップキャストは型システムに違反します) を参照していないことがコンパイル時に簡単に推測できます。参照されるオブジェクトの正確な型は実行前にわかっているため、使用されているプログラミング言語で多重継承がサポートされているか単一継承のみがサポートされているかに応じて1 つ以上の仮想メソッド テーブル検索を必要とする遅延バインディング(動的ディスパッチとも呼ばれる) の代わりに、早期バインディング(静的ディスパッチとも呼ばれる)を使用できます。
オーバーライドできないメソッド
クラスがサブクラス化できないのと同様に、メソッド宣言にはメソッドがオーバーライドされるのを防ぐメソッド修飾子 (つまり、サブクラスで同じ名前と型シグネチャを持つ新しい関数に置き換えられる) が含まれる場合があります。プライベートメソッドは、メンバー関数であるクラス以外のクラスからはアクセスできないため、オーバーライドできません (ただし、これは C++ には当てはまりません)。Javafinalのメソッド、sealedC# のメソッド、またはfrozenEiffel の機能はオーバーライドできません。
仮想メソッド
スーパークラスのメソッドが仮想メソッドである場合、スーパークラスのメソッドの呼び出しは動的にディスパッチされます。言語によっては、メソッドを明示的に仮想として宣言する必要があります (例: C++)。また、すべてのメソッドが仮想である言語もあります (例: Java)。非仮想メソッドの呼び出しは常に静的にディスパッチされます (つまり、関数呼び出しのアドレスはコンパイル時に決定されます)。静的ディスパッチは動的ディスパッチよりも高速で、インライン展開などの最適化が可能です。
継承されたメンバーの可視性
次の表は、C++で確立された用語を使用して、クラスの派生時に与えられた可視性に応じてどの変数と関数が継承されるかを示しています。[14]
アプリケーション
継承は、2 つ以上のクラスを相互に関連付けるために使用されます。
上書き

多くのオブジェクト指向プログラミング言語では、クラスまたはオブジェクトが、継承した側面(通常は動作)の実装を置き換えることができます。このプロセスはオーバーライドと呼ばれます。オーバーライドによって、継承されたクラスのインスタンスが使用する動作のバージョン(そのクラスの一部であるもの、または親(基本)クラスのもの)が複雑になります。その答えはプログラミング言語によって異なり、一部の言語では、特定の動作はオーバーライドされず、基本クラスの定義どおりに動作する必要があることを示す機能が用意されています。たとえば、C#では、基本メソッドまたはプロパティは、virtual、abstract、またはoverride修飾子でマークされている場合にのみサブクラスでオーバーライドできますが、Javaなどのプログラミング言語では、別のメソッドを呼び出して他のメソッドをオーバーライドできます。[15]オーバーライドの代替手段は、継承されたコードを非表示にすることです。
コードの再利用
実装継承は、サブクラスが基本クラスのコードを再利用するメカニズムです。デフォルトでは、サブクラスは基本クラスのすべての操作を保持しますが、サブクラスは一部またはすべての操作をオーバーライドして、基本クラスの実装を独自のものに置き換えることができます。
次の Python の例では、サブクラスSquareSumComputerとCubeSumComputer が、基本クラスSumComputerのtransform()メソッドをオーバーライドします。基本クラスは、2 つの整数の平方和を計算する演算で構成されています。サブクラスは、数値を平方に変換する演算を除いて基本クラスのすべての機能を再利用し、数値をそれぞれ平方と立方に変換する演算に置き換えます。したがって、サブクラスは 2 つの整数の平方/立方和を計算します。
以下はPythonの例です。
クラス SumComputer :
def __init__ ( self , a , b ):
self . a = a
self . b = b
def transform ( self , x ):
NotImplementedErrorを発生させる
def inputs ( self ):
return range ( self . a , self . b )
def compute ( self ):
return sum ( self . transform ( value ) for value in self . inputs ())
クラス SquareSumComputer ( SumComputer ):
def transform ( self , x ):
return x * x
クラス CubeSumComputer ( SumComputer ):
def transform ( self , x ):
return x * x * x
ほとんどの方面では、コードの再利用のみを目的としたクラス継承は支持されなくなっています。[要出典]主な懸念は、実装継承では多態的な代替可能性が保証されないことです。再利用クラスのインスタンスは、継承されたクラスのインスタンスに必ずしも置き換えられるわけではありません。代替手法である明示的な委任では、プログラミングの手間は増えますが、代替可能性の問題は回避できます。[要出典] C++ では、代替可能性のない実装継承の形式としてプライベート継承を使用できます。パブリック継承は「is-a」関係を表し、委任は「has-a」関係を表しますが、プライベート (および保護された) 継承は「isimplemented in the terms of」関係と考えることができます。[16]
継承のもう1つのよくある用途は、クラスが特定の共通インターフェースを維持すること、つまり同じメソッドを実装することを保証することです。親クラスは、実装された操作と子クラスで実装される操作の組み合わせにすることができます。多くの場合、スーパータイプとサブタイプの間にインターフェースの変更はありません。子は親クラスの代わりに記述された動作を実装します。[17]
継承とサブタイプ
継承はサブタイピングと似ていますが、異なります。[4]サブタイピングにより、特定の型を別の型または抽象化で置き換えることができ、言語サポートに応じて暗黙的または明示的に、サブタイプと既存の抽象化の間に is -a関係を確立すると言われています。サブタイピングメカニズムとして継承をサポートする言語では、この関係は継承によって明示的に表現できます。たとえば、次の C++ コードは、クラスBとAの間に明示的な継承関係を確立します。ここで、 B はAのサブクラスおよびサブタイプであり、 Bが指定されている場合はどこでも(参照、ポインター、またはオブジェクト自体を介して) Aとして使用できます。
クラスA { public : void DoSomethingALike () const {} };
クラスB : public A { public : void DoSomethingBLike () const {} };
void UseAnA ( const A & a ) { a . DoSomethingALike (); }
void SomeFunc () { B b ; UseAnA ( b ); // b は A の代わりに使用できます。 }
継承をサブタイピングのメカニズムとしてサポートしないプログラミング言語では、基底クラスと派生クラスの関係は、型間の関係と比較すると、実装間の関係(コード再利用のメカニズム)にすぎません。継承をサブタイピングのメカニズムとしてサポートするプログラミング言語であっても、継承は必ずしも動作のサブタイピングを伴うわけではありません。親クラスが期待されるコンテキストで使用されるとオブジェクトが誤って動作するクラスを派生させることは完全に可能です。リスコフの置換原則を参照してください。[18](connotation/denotationと比較してください。)一部のOOP言語では、サブタイプを宣言する唯一の方法は、別のクラスの実装を継承する新しいクラスを定義することであるため、コードの再利用とサブタイピングの概念が一致しています。
設計上の制約
プログラムの設計で継承を広範に使用すると、特定の制約が課せられます。
たとえば、人物の名前、生年月日、住所、電話番号を含むPersonクラスを考えてみましょう。人物の成績平均点と履修科目を含むStudentというPersonのサブクラスと、人物の役職、雇用主、給与を含む EmployeeというPersonの別のサブクラスを定義できます。
この継承階層を定義する際に、すでに特定の制限を定義しましたが、そのすべてが望ましいわけではありません。
- 独身
- 単一継承を使用すると、サブクラスは 1 つのスーパークラスのみを継承できます。上記の例を続けると、PersonオブジェクトはStudentまたはEmployee のいずれかになりますが、両方になることはできません。多重継承を使用すると、 StudentとEmployeeの両方を継承するStudentEmployeeクラスを定義できるため、この問題は部分的に解決されます。ただし、ほとんどの実装では、各スーパークラスから継承できるのは 1 回だけであるため、学生が 2 つの仕事に就いたり、2 つの教育機関に通ったりするケースはサポートされません。Eiffel で使用可能な継承モデルは、反復継承をサポートすることでこれを可能にします。
- 静的
- オブジェクトの継承階層は、オブジェクトの型が選択されたときにインスタンス化時に固定され、時間の経過とともに変化しません。たとえば、継承グラフでは、 StudentオブジェクトがPersonスーパークラスの状態を保持したままEmployeeオブジェクトになることはできません。(ただし、この種の動作は、デコレータ パターンで実現できます。) 継承を批判する人もいます。継承は、開発者を元の設計標準に縛り付けると主張しています。[19]
- 可視性
- クライアント コードがオブジェクトにアクセスできるときは、通常、そのオブジェクトのスーパークラスのデータすべてにアクセスできます。スーパークラスが public と宣言されていない場合でも、クライアントはオブジェクトをスーパークラスの型にキャストできます。たとえば、学生の成績平均点と成績証明書へのポインターを関数に渡すには、その関数に学生のPersonスーパークラスに格納されている個人データすべてへのアクセスも与える必要があります。C++ や Java などの多くの最新言語では、継承チェーンの外部のコードがデータにアクセスできないようにしながら、サブクラスがデータにアクセスできるようにする「保護された」アクセス修飾子が提供されています。
複合再利用の原則は、継承に代わるものです。この手法は、動作を主要なクラス階層から分離し、ビジネス ドメイン クラスで必要な特定の動作クラスを含めることで、ポリモーフィズムとコードの再利用をサポートします。このアプローチでは、実行時に動作を変更できるようにすることでクラス階層の静的な性質を回避し、1 つのクラスが祖先クラスの動作に制限されることなく、ビュッフェ スタイルで動作を実装できるようにします。
問題点と代替案
実装継承は、少なくとも 1990 年代から、オブジェクト指向プログラミングのプログラマーや理論家の間で議論の的となっている。彼らの中には、代わりにインターフェース継承を主張し、継承よりも構成を好むDesign Patternsの著者もいる。たとえば、クラス間の継承の静的な性質を克服するために、デコレータ パターン (前述のとおり) が提案された。同じ問題に対するより根本的な解決策として、ロール指向プログラミングでは、継承と構成の特性を新しい概念に組み合わせた、 played-by という明確な関係を導入している。[要出典]
Allen Holubによると、実装継承の主な問題は、「脆弱な基底クラス問題」の形で不要な結合が導入されることです。[6]基底クラスの実装を変更すると、サブクラスの動作が意図せず変更される可能性があります。インターフェイスを使用すると、実装は共有されず、APIのみが共有されるため、この問題を回避できます。[19]別の言い方をすると、「継承はカプセル化を破壊する」ということです。[20]この問題は、クライアントコードがシステム提供のクラスを継承し、アルゴリズムでシステムのクラスに置き換えられることが期待されるフレームワークなどのオープンオブジェクト指向システムで明確に発生します。[6]
伝えられるところによると、Javaの発明者であるジェームズ・ゴスリングは実装継承に反対しており、Javaを再設計するなら実装継承は含めないと述べた。[19]継承をサブタイプ化(インターフェース継承)から切り離す言語設計は、1990年には早くも登場した。[21]その現代的な例としては、Goプログラミング言語がある。
複雑な継承、または十分に成熟していない設計内で使用される継承は、ヨーヨー問題につながる可能性があります。 1990 年代後半に継承がプログラムを構造化するための主要なアプローチとして使用されていたとき、開発者はシステム機能が拡張するにつれて、コードをより多くの継承レイヤーに分割する傾向がありました。開発チームが複数の継承レイヤーを単一責任の原則と組み合わせると、非常に薄いコード レイヤーが多数作成され、多くのレイヤーが実際のコードが 1 行または 2 行のみで構成されていました。[要出典]レイヤーが多すぎると、どのレイヤーをデバッグする必要があるかを判断するのが難しくなるため、デバッグが大きな課題になります。
継承に関するもう 1 つの問題は、サブクラスをコードで定義する必要があることです。つまり、プログラム ユーザーは実行時に新しいサブクラスを追加できません。その他の設計パターン ( Entity–component–systemなど) では、プログラム ユーザーが実行時にエンティティのバリエーションを定義できます。
参照
- アーキタイプパターン – ソフトウェア設計パターン
- 円と楕円の問題
- 無効化可能な推論 – 演繹的には有効ではないが、合理的に説得力のある推論
- インターフェース(コンピューティング) – コンピューティング システムの要素間の共有境界
- メソッドオーバーライド – オブジェクト指向プログラミングにおける言語機能
- Mixin – オブジェクト指向プログラミング言語のクラス
- ポリモーフィズム(コンピュータサイエンス) - 複数の異なる型に関して1つのインターフェースまたはシンボルを使用する
- プロトコル – クラスの抽象化
- ロール指向プログラミング – オブジェクトの概念的理解に基づいたプログラミングパラダイム
- 特性(コンピュータプログラミング) – クラスの機能を拡張するメソッドのセット
- 仮想継承 – C++ 言語のテクニック
注記
参考文献
- ^ Johnson, Ralph (1991 年 8 月 26 日)。「再利用可能なクラス の設計」(PDF) 。www.cse.msu.edu。
- ^ Madsen, OL (1989)。「仮想クラス: オブジェクト指向プログラミングにおける強力なメカニズム」。オブジェクト指向プログラミング システム、言語、アプリケーションに関する会議議事録 - OOPSLA '89 。pp . 397–406。doi :10.1145/74877.74919。ISBN 0897913337.S2CID 1104130 。
- ^ Davies, Turk (2021).コンピュータビジョンにおける高度な手法とディープラーニングエルゼビアサイエンス pp. 179–342.
- ^ ab Cook, William R.; Hill, Walter; Canning, Peter S. (1990).継承はサブタイプ化ではない。第17回ACM SIGPLAN- SIGACTプログラミング言語の原則に関するシンポジウム(POPL)の議事録。pp. 125–135。CiteSeerX 10.1.1.102.8635。doi : 10.1145 / 96709.96721。ISBN 0-89791-343-4。
- ^ Cardelli, Luca (1993).タイプフルプログラミング(技術レポート). Digital Equipment Corporation . p. 32–33. SRC 研究レポート 45.
- ^ abc Mikhajlov, Leonid; Sekerinski, Emil (1998). 脆弱な基本クラスの問題に関する研究(PDF) .第 12 回ヨーロッパオブジェクト指向プログラミング会議 (ECOOP) の議事録。コンピュータサイエンスの講義ノート。第 1445 巻。Springer。pp. 355–382。doi :10.1007/ BFb0054099。ISBN 978-3-540-64737-9. 2017年8月13日時点のオリジナル(PDF)からアーカイブ。2015年8月28日閲覧。
- ^ Tempero, Ewan; Yang, Hong Yul; Noble, James (2013). Java でプログラマが継承を使って行うこと(PDF) . ECOOP 2013–オブジェクト指向プログラミング. コンピュータサイエンスの講義ノート. Vol. 7920. Springer. pp. 577–601. doi :10.1007/978-3-642-39038-8_24. ISBN 978-3-642-39038-8。
- ^ Hoare, CAR (1966). レコード処理(PDF) (技術レポート). pp. 15–16.
- ^ Dahl, Ole-Johan ; Nygaard, Kristen (1967 年 5 月). クラスとサブクラスの宣言(PDF) . IFIP シミュレーション言語ワーキング カンファレンス。オスロ: ノルウェー コンピューティング センター。
- ^ Dahl, Ole-Johan (2004)。「オブジェクト指向の誕生: Simula 言語」(PDF) 。オブジェクト指向から形式手法へ。コンピュータサイエンスの講義ノート。第 2635 巻。pp. 15–25。doi : 10.1007/978-3-540-39993-3_3。ISBN 978-3-540-21366-6。
- ^ 「C++ 継承」www.cs.nmsu.edu。 2023年9月24日時点のオリジナルよりアーカイブ。2018年5月16日閲覧。
- ^ Stroustrup, Bjarne (1994). C++ の設計と進化. ピアソン. p. 417. ISBN 9780135229477。
- ^ Schildt, Herbert (2003). The complete reference C++ . Tata McGraw Hill. p. 417. ISBN 978-0-07-053246-5。
- ^ Balagurusamy, E. (2010). C++ によるオブジェクト指向プログラミング。Tata McGraw Hill。p. 213。ISBN 978-0-07-066907-9。
- ^ override(C# リファレンス)
- ^ 「GotW #60: 例外安全なクラス設計、パート 2: 継承」。Gotw.ca。2012年 8 月 15 日閲覧。
- ^ ヴェヌゴパル、KR;ブヤ、ラージクマール (2013)。C++ をマスターする。タタ・マグロウ・ヒル・エデュケーション・プライベート・リミテッド。 p. 609.ISBN 9781259029943。
- ^ ミッチェル、ジョン(2002)。「10 オブジェクト指向言語の概念」 「プログラミング言語の概念」ケンブリッジ大学出版局。p. 287。ISBN 978-0-521-78098-8。
- ^ abc Holub, Allen (2003年8月1日). 「なぜextendsは邪悪なのか」。2019年2月24日時点のオリジナルよりアーカイブ。2015年3月10日閲覧。
- ^ Seiter, Linda M.; Palsberg, Jens; Lieberherr, Karl J. (1996). 「コンテキスト関係を使用したオブジェクトの動作の進化」ACM SIGSOFT ソフトウェア エンジニアリング ノート. 21 (6): 46. CiteSeerX 10.1.1.36.5053 . doi :10.1145/250707.239108.
- ^ アメリカ、ピエール (1991)。動作サブタイプによるオブジェクト指向プログラミング言語の設計。オブジェクト指向言語の基礎に関する REX スクール/ワークショップ。コンピュータサイエンスの講義ノート。第 489 巻。pp. 60–90。doi : 10.1007/ BFb0019440。ISBN 978-3-540-53931-5。
さらに読む
- Meyer, Bertrand (1997)。「24. 継承の適切な使用」(PDF)。オブジェクト指向ソフトウェア構築(第 2 版)。Prentice Hall。pp. 809–870。ISBN 978-0136291558。
- Samokhin , Vadim (2017)。「実装継承は悪である」。HackerNoon。Medium 。
