Composition
Parts has a Part
Parts classの内部に、Part classのinstanceを持つ
そのPartは、そのPartsに専属するようなpartなのか?
他のPartsから使用されることは想定されなくてよいのか
だとすると、「関数型っぽい」を中途半端に実現するものだと捉えられる
汎用性のない小さい部品を作っている感じ
ソレでのみ使われることを想定してそのPartを定義するの?
だとすれば、そのPartが別のclassから使用されないことについて何か表明したりはするの?
しないと全然使われうると思うけど
兄弟関係にあるPartたちはInterfaceは統一されているべき、みたいな制約はあるのか?
これただのDIの時に出てきたようなやつじゃん?
これにコンポジションと名付けるほどの利点があるの?
下のコード例ではどれがPartに相当するの?
tsの小さい例
これ読めば雰囲気はわかるなmrsekut.icon
ほぼ同じ内容の、PHP版
個々のPartはconstructorも持っていない
関数を使いたいがためのclass作成
code:php
class Animal {
function eat() {
echo "Eating...<br>";
}
}
命名
Functionality classes like Pushable are often named with “able”, “can” or “has”. Like Flyable, CanDrive, HasFood etc.
OOPの敗北という雰囲気を感じるmrsekut.icon
関数型指向に寄っているが、完全に寄れていない中途半端な感じがする
それでも元のよりはかなりマシ
「has-a」関係を持ち、かつ、包含される側のオブジェクトが包含する側のオブジェクトから独立して存在しえない
Partは、対応するParts経由でのみ使われる
Partsなしで、Part独立では使われない
馴染みが無いのでパッとおもいだせない
ので、小さいコード片を用意しておきたいmrsekut.icon
super class
code:ts
class Person {
private name: string;
private age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
getName(): string {
return this.name;
}
getAge(): number {
return this.age;
}
}
継承を使ってStudnetを作った場合
code:ts
class StudentE extends Person {
private grade: number;
constructor(name: string, age: number, grade: number) {
super(name, age);
this.grade = grade;
}
getGrade(): number {
return this.grade;
}
}
const yamada = new StudentE("yamada", 20, 1);
const yn = yamada.getName();
コンポジションを使ってSturudentを作った場合
code:ts
class StudentC {
private Person: Person;
private grade: number;
constructor(person: Person, grade: number) {
this.Person = person;
this.grade = grade;
}
getName() {
return this.Person.getName();
}
getAge() {
return this.Person.getAge();
}
getGrade() {
return this.grade;
}
}
const tanaka = new StudentC(new Person("tanaka", 20), 1);
const tn = tanaka.getName();
「コンポジション」でググって日本語であまりまともな記事が出てこない..mrsekut.icon
その周辺の知識が弱いので単にmrsekut.iconのググり能力のせいかもしれないが。
継承との違い
クラス階層の構造には依存しない
自身のメッセージは自身で移譲する
コンポジションと継承の選択
コンポジションのほうが圧倒的に依存が少ない
コンポジションのメリット
小さなオブジェクトが自然といくつも作られるようになる
コンポーズされるオブジェクトがロールを表すことで、責任が明解であり、明確に定義されたインタフェースを介してアクセス可能になる コンポーズされたオブジェクトはわずかなコードしか継承せず、階層構造にあるコードの変更によって生じる副作用に悩まなくて良い
構造的に独立していることで、適切に定義されたインタフェースをもつ他のオブジェクトと簡単に交換可能
兄弟関係にあるPartたちは互いに同じInterfaceを持つようにするのねmrsekut.icon
コンポジションのデメリット
コンポーズされたオブジェクト(パーツ)それぞれは小さく、責任が明確であっても、パーツが組み合わさった全体では理解し難いものである可能性がある
構造的な独立性の利点はメッセージの自動的な委譲を犠牲にしている
コンポーズされたオブジェクトは明示的にどのメッセージを移譲するか知っている必要がある
全く同一の移譲のコードが多岐にわたるオブジェクトに必要になるかもしれない
instance変数がめっちゃ増えそう