[オブジェクト向けプログラミング入門]継承ではなくアセンブリ


継承と再利用

  • は、親の再使用および拡張に使用できる機能を継承する.
  • 機能の再使用の欠点を継承することで

  • プレミアムの変更は難しい
  • 親が少し変更された場合、他の子の動作が正しくない可能性があります.
  • クラス増加
  • 継承するとサブクラスが増加し、複雑さが増加します.
  • を継承すると誤用される可能性があります.
        public class Container extends ArrayList<Luggage> {
        	private int maxSize;
        	private int currentSize;
    
        	public Container(int maxSize){
        		this.maxSize = maxSize;
        	}
    
        	public void put(Luggate lug) throws NotEnoughSpaceException {
        		if(!canContain(lug)) throw new NotEnoughSpaceException();
        		super.add(lug);
        		currentSize += lug.size();
        	}
        	
        	public void extract(Luggage lug){
        		super.remove(lug);
        		this.currentSize -= lug.size();
        	}
        	
        	public boolean canContain(Luggage lug){
        		return maxSize >= currentSize + lug.size();
        	}
        }
    上記のContainerクラスはArrayListを継承し実現した.Containerクラスは、putおよびextractが上位クラスであるArrayListおよびaddを用いて実現される.

    正しい使い方は上図のように、IDEが継承した親のメソッドを推奨として表示するため、開発者は望ましくない操作を誤用する可能性があります.
    これは誤って使用した開発者の問題ですか?
    Nope. 誤用される可能性のあるクラスを作成するユーザの問題

    引き継いだ欠点解決方法→組み立てる

  • 組合せ
  • は、より複雑な機能
  • を提供するために複数のオブジェクトを組み合わせる.
  • は、一般フィールドが他のオブジェクトを参照するように、
  • を組み立てる.
  • 必要に応じてオブジェクト
  • を作成または取得する.
    public class FlowController {
    	private Encryptor encryptor = new Encryptor(); // 필드로 객체를 생성하여 조립
    	
    	public void process() {
    		//...
    		byte[] encrytepdData = encryptor.encrypt(data);
    		//...
    	}
    }

    アセンブリによる機能の再使用



    オブジェクトをフィールドとして使用し、ストレージクラスを継承しません.

    継承誤用問題の解決

    public class Container {
    	private int maxSize;
    	private int currentSize;
    	private List<Luggage> luggages = new ArrayList<>(); // 필드로 사용
    
    	public Container(int maxSize){
    		this.maxSize = maxSize;
    	}
    
    	public void put(Luggate lug) throws NotEnoughSpaceException {
    		if(!canContain(lug)) throw new NotEnoughSpaceException();
    		luggages.add(lug);
    		currentSize += lug.size();
    	}
    	
    	public void extract(Luggage lug){
    		luggages.remove(lug);
    		this.currentSize -= lug.size();
    	}
    	
    	public boolean canContain(Luggage lug){
    		return maxSize >= currentSize + lug.size();
    	}
    }
    前述したように,removeを継承しなければ,フィールドを用いて実現され,誤用の可能性はなくなる.

    継承ではなくアセンブリ

  • を継承する前に、
  • がアセンブリできないかどうかを確認します.
    継承
  • が真のサブタイプである場合にのみ、継承
  • が使用されます.