コンポジション
日本語 | 混合物 |
英語 | composition |
ふりがな | こんぽじしょん |
フリガナ | コンポジション |
あるクラスの機能を持つクラスのこと。
特定のクラスの機能を、自分が作るクラスにも持たせたい場合に、継承を使わずフィールドとしてそのクラスを持ち、そのクラスのメソッドを呼び出すメソッドを持たせること。そうすることで、クラスに他のクラスの機能を組み込むことができる。
オブジェクト指向用語。
厳密なオブジェクト指向では、継承は「機能の継承」を目的とせず、「スーパークラスはサブクラスの一種である」といういわゆる「is-a」の関係を持たなければならない。
そのため、単に機能を持たせたい場合には、継承ではなくコンポジションとすることが推奨される。
メリットとして、「機能の継承」はクラスの関連図をイメージする際に分かりにくくなりやすいためそれを回避できる、メソッドをワンクッション置くことで融通が効く、といったものがある。また、コンポジションの対象となるクラスは、そのサブクラスも使用できることになる。
デメリットとしては、同じメソッドを作らなければならない、コンポジションの対象となるクラスに変更があった場合には同じように変更しなければならない場合がある、等である。
Java的には、言語仕様上特別なことは必要なく、単にフィールドとして別クラスを持ち、その別クラスを呼び出すメソッドを作ればよい。
つまり、コンポジションとはシンタックスではなくセマンティクスな用語である。
似たようなものに「集約」がある。
コンポジションと集約は非常に似ており、オブジェクト指向の常としてこの両者は曖昧である。
一応、コンポジションは集約の一種であるとされる。集約の中でも元のクラスと対象のクラスの結び付きが強く、寿命が同じであるという差異があるが、インスタンスがガベージコレクションによって削除されるため明確な寿命が存在しないJavaでは、実装上その差を付けることは難しい。
特定のクラスの機能を、自分が作るクラスにも持たせたい場合に、継承を使わずフィールドとしてそのクラスを持ち、そのクラスのメソッドを呼び出すメソッドを持たせること。そうすることで、クラスに他のクラスの機能を組み込むことができる。
オブジェクト指向用語。
厳密なオブジェクト指向では、継承は「機能の継承」を目的とせず、「スーパークラスはサブクラスの一種である」といういわゆる「is-a」の関係を持たなければならない。
そのため、単に機能を持たせたい場合には、継承ではなくコンポジションとすることが推奨される。
メリットとして、「機能の継承」はクラスの関連図をイメージする際に分かりにくくなりやすいためそれを回避できる、メソッドをワンクッション置くことで融通が効く、といったものがある。また、コンポジションの対象となるクラスは、そのサブクラスも使用できることになる。
デメリットとしては、同じメソッドを作らなければならない、コンポジションの対象となるクラスに変更があった場合には同じように変更しなければならない場合がある、等である。
Java的には、言語仕様上特別なことは必要なく、単にフィールドとして別クラスを持ち、その別クラスを呼び出すメソッドを作ればよい。
つまり、コンポジションとはシンタックスではなくセマンティクスな用語である。
似たようなものに「集約」がある。
コンポジションと集約は非常に似ており、オブジェクト指向の常としてこの両者は曖昧である。
一応、コンポジションは集約の一種であるとされる。集約の中でも元のクラスと対象のクラスの結び付きが強く、寿命が同じであるという差異があるが、インスタンスがガベージコレクションによって削除されるため明確な寿命が存在しないJavaでは、実装上その差を付けることは難しい。
参考サイト
- (参考サイトはありません)
// Sample.java
public class Sample
{
public static void main( String[] args )
{
// コンポジションクラスを使ってみます。
StringBufferComposition compo = new StringBufferComposition();
compo.append( "あいうえお\n" );
compo.append( "かきくけこ\n" );
compo.append( "さしすせそ\n" );
System.out.println( compo.toString() );
// あいうえお
// かきくけこ
// さしすせそ
}
}
/**
* StringBufferのコンポジションクラス。
*/
class StringBufferComposition
{
/**
* コンポジションの対象クラス。
*/
private StringBuffer strbuf = new StringBuffer();
/**
* 文字列を追加します。
*/
public StringBufferComposition append( String string )
{
strbuf.append( string );
return this;
}
/**
* 文字列を取得します。
*/
public String toString()
{
return strbuf.toString();
}
}
public class Sample
{
public static void main( String[] args )
{
// コンポジションクラスを使ってみます。
StringBufferComposition compo = new StringBufferComposition();
compo.append( "あいうえお\n" );
compo.append( "かきくけこ\n" );
compo.append( "さしすせそ\n" );
System.out.println( compo.toString() );
// あいうえお
// かきくけこ
// さしすせそ
}
}
/**
* StringBufferのコンポジションクラス。
*/
class StringBufferComposition
{
/**
* コンポジションの対象クラス。
*/
private StringBuffer strbuf = new StringBuffer();
/**
* 文字列を追加します。
*/
public StringBufferComposition append( String string )
{
strbuf.append( string );
return this;
}
/**
* 文字列を取得します。
*/
public String toString()
{
return strbuf.toString();
}
}
// Sample.java public class Sample { public static void main( String[] args ) { // コンポジションクラスを使ってみます。 StringBufferComposition compo = new StringBufferComposition(); compo.append( "あいうえお\n" ); compo.append( "かきくけこ\n" ); compo.append( "さしすせそ\n" ); System.out.println( compo.toString() ); // あいうえお // かきくけこ // さしすせそ } } /** * StringBufferのコンポジションクラス。 */ class StringBufferComposition { /** * コンポジションの対象クラス。 */ private StringBuffer strbuf = new StringBuffer(); /** * 文字列を追加します。 */ public StringBufferComposition append( String string ) { strbuf.append( string ); return this; } /** * 文字列を取得します。 */ public String toString() { return strbuf.toString(); } }