構成たたは継承遞択方法

はじめに...


...構成、継承、コヌドはありたせんでした。


そしお、コヌドは䞍噚甚で、繰り返しがあり、分離できず、悲惚で、冗長で䜿い尜くされおいたした。


コヌドの再利甚の䞻なツヌルは、コピヌペヌストでした。 手続きず機胜はめったにない、疑わしい新しいものです。 治療を呌び出すこずは高䟡な喜びでした。 メむンロゞックから分離されたコヌドの䞀郚は困惑しおいたした


悲芳的な時代があった。


しかし、その埌、OOPの光線が䞖界䞭に茝きたした...確かに、数十幎間1誰もこれに気づきたせんでした。 GUI 2が登堎するたでは、結局のずころ、OOPが非垞に䞍足しおいたした。 りィンドり内のボタンをクリックするず、ボタンたたはその代衚にメッセヌゞ「Pressing」 3を送信しお結果を取埗するよりも簡単なこずは䜕ですか


そしお、OOPが始たりたした。 倚くの4冊の本が曞かれおおり、数え切れないほどの5぀の蚘事が飌育されおいたす。 それで今日、誰でもオブゞェクト指向プログラミングを行うこずができたすよね



悲しいかな、コヌドおよびむンタヌネットはそれが間違っおいるず蚀っおいたす


最も熱烈な議論ず最倧の誀解は、しばしば「 継承よりも合成を奜む 」ずいうマントラによっお衚される、構成ず継承の間の遞択を匕き起こすようです。 これに぀いおお話したす。


マントラが害を及がすずき


私はマントラのファンではありたせんが、日垞生掻では、「継承よりも構成を優先する」こずは䞀般に普通です 。 圌らはしばしば真実の粒を持っおいるずいう事実にもかかわらず、誘惑に屈し、スロヌガンに無頓着に远いかけるこずはあたりにも簡単であり、その背埌に隠されおいるものを理解しおいたせん。 そしお、それは垞に暪に出おきたす。


「Inheritance is Evil」 6のような芋出しのある黄undの蚘事も、特に著者が最初に継承を誀っお適甚し、それがすべおのせいだず結論づけるこずによっお䞋曞きを正圓化しようずする堎合、私には向いおいたせん。 たあ、「ハンマヌを吞うのは、圌らがねじをねじ蟌むこずができないからです」のように。


基本から始めたしょう。


定矩


蚘事の埌半で、OOPは、プロパティ、メ゜ッド、および単玔な単䞀の継承を持぀クラスをサポヌトする「クラシック」オブゞェクト蚀語ずしお理解したす。 むンタヌフェむス、䞍玔物、アスペクト、倚重継承、デリゲヌト、クロヌゞャ、ラムダはありたせん-最もシンプルなものだけです



継承は基本です


継承は、OOPの基本抂念です。 プログラミング蚀語にはオブゞェクトずメッセヌゞがありたすが、継承がなければオブゞェクト指向ではありたせんオブゞェクトのみに基づいおいたすが、ポリモヌフィックのたたです。


...構成のように


構成は、あらゆる蚀語の基本的な特性でもありたす。 蚀語が構成をサポヌトしおいない堎合でもこれは最近では珍しいこずですが、人々は䟝然ずしお郚品やコンポヌネントの芳点から考えるでしょう。 構成がなければ、郚品の耇雑な問題を解決するこずは䞍可胜です。


カプセル化も基本的なこずですが、今では圌女に぀いおではありたせん


それで、倧隒ぎは䜕からですか


さお、構成ず継承の䞡方が基本ですが、問題は䜕ですか


しかし、実際には、䞀方が他方を垞に眮き換えるこずができる、たたは最初の方が2番目よりも良いたたは悪いず考えるかもしれたせん。 ゜フトりェア開発は垞に合理的なバランス、劥協の遞択です。


構成は倚かれ少なかれ単玔で、私たちは人生で絶えず遭遇しおいたす。怅子には脚があり、壁にはレンガやセメントなどがありたす。 しかし、継承は、その単玔な定矩にもかかわらず、適甚方法に぀いお慎重に考えないず、すべおを耇雑にし、混乱させる可胜性がありたす。 継承は非垞に抜象的なものであり、それに぀いお話すこずはできたすが、觊れないでください。 もちろん、コンポゞションを䜿甚しお継承を暡倣するこずもできたすが、これは通垞は倧隒ぎです。 合成の目的は䜕ですか明らかなこずは、郚品から党䜓を組み立おるこずです。 しかし、継承はより困難です。なぜなら、それは䞀床に玄2぀のこずだからです意味ずメカニズムに぀いお。


意味的継承


生物孊のように、分類矀の分類はそれらを階局に線成するため、継承は䞻題領域からの抂念の階局を反映したす。 䞀般的なものから特定のものたでそれらを敎理し、関連するアむデアを階局ツリヌのブランチに収集したす。 クラスの意味セマンティクスは、ほずんどの郚分がむンタヌフェヌスで衚珟されたす-クラスが理解できるメッセヌゞのセットですが、クラスが応答するメッセヌゞによっおも決定されたす。 祖先から継承-祖先が理解できるすべおのメッセヌゞを理解するだけでなく、祖先の振る舞いを保持するために玄Per。答えるこずもできるように芪切にしおください。コンポヌネントずしおの祖先むンスタンス。 クラスが完党にシンプルで、ほずんどロゞックを持たず、その名前に倧きな意味的負荷がかかっおいる堎合でも、開発者はサブゞェクト領域に関する重芁な結論を導き出すこずに泚意しおください。


機械的継承


継承に぀いお機械的に蚀えば、継承は基本クラスのデヌタフィヌルドず動䜜メ゜ッドを受け取り、それらを再利甚したり、継承者に远加したりできるこずを意味したす。 メカニズムの芳点から、子孫が祖先の実装コヌドを継承する堎合、そのむンタヌフェむスは必然的に受信されたす。


ほずんどのオブゞェクト指向蚀語における継承7のこの二重の性質は、誀解のせいだず確信しおいたす。 倚くの人々は、継承はコヌドを再利甚するこずだず信じおいたすが、それはそれだけではありたせん。 再利甚のために過剰䜿甚が䞎えられた堎合、アヌキテクチャの灜害を埅ちたす。 以䞋に䟋をいく぀か瀺したす。


継承しない方法。 䟋1


 class Stack extends ArrayList { public void push(Object value) { 
 } public Object pop() { 
 } } 

クラスStackように芋えたすが、すべお順調です。 しかし、そのむンタヌフェヌスを泚意深く芋おください。 Stackず呌ばれるクラスには䜕が必芁ですか push()およびpop()メ゜ッド、その他。 そしお私たちず get() 、 set() 、 add() 、 remove() 、 clear() 、およびArrayListから継承されたArrayListのゞャンクがありたす。これらはスタックにはたったく必芁ありたせん。


望たしくないすべおのメ゜ッドを再定矩するこずは可胜です。たた、䞀郚たずえばclear() はニヌズに合わせお調敎するこずもできたすが、1぀の蚭蚈゚ラヌのために少し手間がかかりたせんか 実際、3぀1぀のセマンティック、1぀の機械的および1぀の組み合わせ


  1. ステヌトメント「Stack is ArrayList」は停です。 Stack ArrayList サブタむプで Stack たせん 。 スタックのタスクは、LIFOルヌルlast come、first goの実装を確実にするこずです。これは、プッシュ/ポップむンタヌフェむスでは簡単に満たされたすが、 ArrayListむンタヌフェむスでは尊重されたせん。
  2. ArrayListから機械的に継承するず、カプセル化がArrayListたす。 クラむアント偎のコヌドは、 ArrayListを䜿甚しおスタック芁玠を栌玍するこずを決定したこずを認識しないでください。
  3. 最埌に、 ArrayListを介しおスタックを実装するには、2぀の異なるサブゞェクト領域を混圚させたすArrayListはランダムアクセスのコレクションであり、スタックは厳密に制限された任意ではないアクセスを持぀キュヌの䞖界の抂念です

最埌の点は䞀芋重芁ではありたせんが、重芁なこずです。 それを詳しく芋おみたしょう。


継承しない方法。 䟋2


継承でよくある間違いは、ドメむンからモデルを䜜成し、完成した実装からモデルを継承するこずです。 したがっお、特定のサブセットで顧客の䞀郚 Customerクラスを遞択する必芁があるずしたしょう。 簡単 ArrayList<Customer>を継承し、 CustomerGroupず呌んでラッシュしたす。


そこにあった。 そうするこずで、2぀の䞻題領域を再び混同したす。 これを避けるようにしおください


  1. ArrayList<Customer>はすでにリストの継承者であり、コレクション型ナヌティリティであり、既成の実装です。
  2. CustomerGroupは完党に異なるものです-サブゞェクト゚リアドメむンからのクラス。
  3. サブゞェクト領域のクラスは実装を䜿甚する必芁があり、それらを継承しないでください。

ドメむン局は、内郚のすべおがそこで行われる方法を知らないはずです。 私たちのプログラムが䜕をしおいるのかに぀いお話すずき、私たちは䞻題分野の抂念で運営しおおり、内郚構造のニュアンスに気を取られたくありたせん。 継承にコヌド再利甚ツヌルのみが含たれおいる堎合、このトラップに䜕床も陥りたす。


単䞀の継承ではありたせん


単䞀継承は、䟝然ずしお最も人気のあるOOPモデルです。 必然的に実装の継承が必芁になり、クラス間の匷力なリンクカップリング-箄Per。に぀ながりたす。 問題は、セマンティックずメカニカルの䞡方の䞡方のニヌズに察応する継承のブランチが1぀しかないこずです。 䞀方に䜿甚するず、もう䞀方には䜿甚できなくなりたす。 もしそうなら、倚重継承はすべおを修正できたすか


いや 継承関係は、むンストルメンタルデヌタ構造、アルゎリズム、ネットワヌクず適甚ビゞネスロゞックのサブゞェクト領域間の境界を越えおはなりたせん。 CustomerGroupがArrayList<Customer>を継承するず同時に、たずえばDemographicSegmentの堎合、2぀のサブゞェクト領域が絡み合い、オブゞェクトの「皮の所属」は明らかになりたせん。


少なくずも私の芳点からはそうするこずが望たしいです。 蚀語で䜿甚可胜なむンストルメンタルクラスを最小限に継承したす。これは、ロゞックの「機械的」郚分を実装するのに十分です。 次に、結果のパヌツをコンポゞションで接続したすが、継承では接続したせん。 蚀い換えれば


他のツヌルのみがツヌルから継承できたす。


これは初心者にずっお非垞によくある間違いです。 それは驚くこずではありたせん。なぜなら、それはずおも簡単に継承できるからです。 これが間違っおいる理由に぀いおの議論に出くわすこずはたれです。 繰り返したすが、ビゞネス゚ンティティはツヌルではなく、ツヌルを䜿甚する必芁がありたす。 パツヌル-個別、カツレツビゞネスモデル-個別。


では、い぀継承が必芁ですか


継承する


ほずんどの堎合-そしお同時に最倧のリタヌン-継承は、互いにわずかに異なるオブゞェクトを蚘述するために䜿甚されたす元の甚語は「差分プログラミング」ずいう甚語を䜿甚したす-およそ。たずえば、小さな远加の特別なボタンが必芁です。 通垞、既存のButtonクラスから継承したす。 新しいクラスはただボタンなので、ButtonクラスのAPI、その動䜜、実装を完党に継承したす。 新しい機胜は既存のものにのみ远加されたす。 ただし、機胜の䞀郚が盞続人から削陀された堎合、これは継承が必芁かどうかを考える機䌚です。


継承は、類䌌の゚ンティティず抂念をグルヌプ化し、クラスのファミリを定矩する堎合、および䞀般的にサブゞェクト領域を説明する甚語ず抂念を敎理する堎合に最も圹立ちたす。 倚くの堎合、サブゞェクトロゞックの倧郚分が既に実装されおいるず、最初に遞択された継承階局が機胜しなくなりたす。 すべお順調に進んだ堎合、これらの階局を分解しお再スタックするこずを恐れないでください9 。


構成たたは継承䜕を遞択したすか


䞡方が適切ず思われる状況では、2぀の平面で蚭蚈を芋おください。


  1. ビゞネスオブゞェクトの構造ず機械的な実行。
  2. 意味ずそれらがどのように盞互䜜甚するかによっお、それらは䜕を意味したす。

継承が同じプレヌン内にある限り、すべおが正垞です。 しかし、階局が䞀床に2぀のプレヌンを通過する堎合、これは悪い症状です。


たずえば、あるオブゞェクトが別のオブゞェクトの䞭にあるずしたす。 内郚オブゞェクトは、倖郚の動䜜の重芁な郚分を実装したす。 倖郚オブゞェクトには、内郚オブゞェクトにパラメヌタを愚かに転送し、その結果を返すプロキシメ゜ッドがたくさんありたす。 この堎合、少なくずも郚分的に内郚オブゞェクトから継承する䟡倀があるかどうかを確認しおください。


もちろん、肩の頭に代わる指瀺はありたせん。 オブゞェクトモデルを構築するずき、䞀般的に考えるこずが有甚です。 ただし、特定のルヌルが必芁な堎合は、お願いしたす。


次の堎合に継承したす。


  1. 䞡方のクラスは同じサブゞェクト領域からのものです。
  2. 盞続人は LSPに関しお祖先の正しいサブタむプです。
  3. 祖先コヌドが必芁であるか、盞続人に適しおいたす
  4. 盞続人は基本的にロゞックを远加したす

これらの条件はすべお同時に満たされる堎合がありたす。



これが圓おはたらない堎合、ほずんどの堎合、継承は必芁ありたせん。 しかし、構成を継承よりも「優先」する必芁があるからではなく、「より良い」からでもありたせん。 特定のアプリケヌションに最適なものを遞択しおください。


これらのルヌルが、2぀のアプロヌチの違いを理解するのに圹立぀こずを願っおいたす。


玠敵なコヌディングをしおください


あずがき


ThoughtWorksの貎重な貢献ずコメントに感謝したす Pete Hogson 、Tim Brown、Scott Robinson、 Martin Fowler 、Mindy Ohr、Sean Newham、 Sam Gibson 、Mahendra Kariya。




1

最初の公匏オブゞェクト指向蚀語であるSIMULA 67は、1967幎に登堎したした。


2

システムおよびアプリケヌションプログラマは、1980幎代半ばにC ++を採甚したしたが、OOPが䞀般に受け入れられるたでにさらに10幎が経過したした。


3

pub / sub、デリゲヌトなどに぀いおは説明せず、意図的に単玔化しお、蚘事が膚らたないようにしたす。


4

この蚘事の執筆時点で、AmazonはOOPに関する24,777本を提䟛しおいたす。


5

「オブゞェクト指向プログラミング」ずいうフレヌズをGoogleで怜玢するず、800䞇件の結果が埗られたす。


6

Google怜玢では、「継承は悪」ずいう結果ずしお37,600の結果が返されたす。


7

蚀語の耇雑さにより、感芚むンタヌフェヌスず機構実行を分離できたす。 D蚀語仕様の䟋を参照しおください。


8

悲しいこずに、Javaでは、 Stack Vectorから継承されたす。


9

継承による再利甚のための蚭蚈は、この蚘事の範囲倖です。 蚭蚈は、基本クラスを䜿甚する人ず盞続人を必芁ずする人の䞡方のニヌズを満たす必芁があるこずに留意しおください。




翻蚳者はTelegramのOOPチャットに感謝したす。


Source: https://habr.com/ru/post/J325478/


All Articles