2017-02-05 14 views
3

私は、次のコード例を持っている:Javaの継承とメソッド解決順序

class p { 
    public void druckauftrag() { 
     // ... 
     drucke(); 
    } 

    public void drucke() { 
     System.out.println("B/W-Printer"); 
    } 
} 

class cp extends p { 
    public void drucke() { 
     System.out.println("Color-Printer"); 
    } 
} 

は、次の行を呼び出す:何の問題なぜ「cp.druckauftrag()を理解することはありません

cp colorprinter = new cp(); 
    cp.druckauftrag(); 

を。 "コンソール出力 "カラープリンタ"になります。

しかし、私は呼ん:

p drucker = (p)colorprinter; 
    drucker.druckauftrag(); 

私は同じ出力を得る - なぜ? タイプキャストは、オブジェクト "drucker"のメソッド "drucke"をcolorprinterの "drucke"で上書きしますか?

ありがとうございました。

+1

わかりやすくするために、クラス名を大文字で表記してください。 –

+1

クラス、mehtodsなどに名前を付けるときは、英語以外の母国語を使用しないでください。English camelCaseを使用してください。 –

+0

クラスタイプは、「外部ユーザー」(他のクラス)によってオブジェクトがどのように見えるかを定義したものです。メソッド実装はインスタンスにバインドされており、型は外部コトグラフを定義するだけです。 – topr

答えて

3

colorprinterは、cpのインスタンスです。たとえあなたがそれをpにアップキャストしたとしても、それはの方法はまだcpの1つになります。

相違点は、あなたがアップキャストcolorprinterの後で、cpが独自に定義するメソッドを呼び出すことができなくなることです。

4

colorprinterはそうpublic void drucke()その実装は、あなたの(p)colorprinterキャストで表現されている何

を変更しない、あなたはそれにキャスト演算子を使用するときcpのインスタンスであることを停止しないの一種でありますオブジェクトcolorprinterが満たすと期待しているコントラクト(インターフェイス)には、署名public void drucke()のパブリックメソッドが含まれていますが、具体的な実装は含まれていません。あなたがタイプpdrucker宣言するとき

と、ところで、このキャスティングはまだ (p) p drucker = (p)colorprinter;で冗長で、暗黙的に実行されます。 p drucker = colorprinter;で十分です。

Here you can learn more about typecasting

抽象クラスまたはインターフェイスから拡張し、抽象メソッド@Override(実装)のみを拡張することをお勧めします。

abstract class BasePrinter { 

    public void druckauftrag() { 
     // ... 
     drucke(); 
    } 

    public void drucke(); 

} 

class p extends BasePrinter {  
    public void drucke() { 
     System.out.println("B/W-Printer"); 
    } 
} 

class cp extends BasePrinter { 
    public void drucke() { 
     System.out.println("Color-Printer"); 
    } 
} 

もちろん、制約は常にそのような再設計を可能にするわけではありません。あなたはプリンタが必要ですか(複数の印刷機能を持つことができることを表現したい場合は、今すぐ

interface Druckable { 
    void drucke(); 
} 

class Druckauftrager { 

    Druckable dk; 
    Druckauftrager(Drukable dk){ 
     this.dk = dk; 
    } 
    public void druckauftrag() { 
     // ... 
     dk.drucke(); 
    } 

} 

class p implements Druckable {  
    public void drucke() { 
     System.out.println("B/W-Printer"); 
    } 
} 

class cp implements Druckable { 
    public void drucke() { 
     System.out.println("Color-Printer"); 
    } 
} 

:基本クラスを拡張するのではなく、コンストラクタ(dependency injection)にパラメータとして基本要件を渡すのも良い代替することができますあなたが好きな色とB/W)の両方のように、あなただけの、たとえば、できるだけ多くの余分なDrukableプロパティおよびコンストラクタのパラメータを持つクラスを記述します。

class BlackAndWhiteOrColorPrinter { 

    p blackAndWhitePrintService; 
    cp colorPrintService; 

    Druckable selectedPrintService; 

    BlackAndWhiteOrColorPrinter (p blackAndWhitePrintService, cp colorPrintService){ 
     this.blackAndWhitePrintService = blackAndWhitePrintService; 
     this.colorPrintService = colorPrintService; 
     this.selectedPrintService = blackAndWhitePrintService; 
    } 

    public void druckauftrag() { 
     // ... 
     selectedPrintService.drucke(); 
    } 

} 

この方法では、あなたもMultiPrinter(List<Druckable> printServices)コンストラクタでclass MultiPrinterを書くことができますその印刷サービスのリストに任意の数の印刷モードを追加する:pcppublic void drucke()Druckableのその他の実装は今後提供されます。単体テストを導入したい場合にはさらに実用的です。例えば、druke()を投げてPaperJamExceptionを投げるなど、テストしたい特定の条件を強制するモックアップオブジェクトを提供することができます。インタフェースは、仕事をオーバーライドし、相続、デファクトスタンダードでも公式java code conventions guideの最新のリビジョンた内容に応じて、そして、ところで

https://docs.oracle.com/javase/tutorial/java/IandI/usinginterface.htmlを参照してください方法の詳細については

、JavaでのクラスはCamelCase命名規則を使用する必要があります。 BlackAndWhitePrinter blackAndWhitePrinterColorPrinter colorPrinterのようなすべての定義でセマンティックネーミングを使用することで、大きなメリットを得ることができます。

0

new演算子を使用してオブジェクトを作成すると、メモリはheapに割り当てられます。メソッドとフィールドは実際にオブジェクトの具体的な実際のクラスに依存します。 サブクラスを変更すると、スーパークラスからビヘイビアが変更され、オーバーライドされたメソッドを呼び出すと、常に変更された動作が発生します。キャストとは、サブクラスのオブジェクトがスーパータイプで表現されるようになったことを意味します。これは、オブジェクトのメソッドの動作が変更された場合、常に変更された動作になります。

は、あなたがそのmangoままfruitとしてmangoを呼び出すが、それでもmangoのようなつまりクラス

public class Fruit{ 
    public void taste(){ 
    System.out.println("depends upon the actual fruit"); 
    } 
} 

public class Mango extends Fruit{ 
    @Override 
    public void taste(){ 
    System.out.println("sweet"); 
    } 
    public void wayToExposeSuperMethod(){ 
    super.taste(); 
    } 
} 

の下にあるとします。 上記のコードの場合

Fruit fruit = new Mango(); 

fruit.taste(); // <-- this will output : sweet 

((Mango)fruit).taste();// <-- this will output : sweet 

fruit.wayToExposeSuperMethod(); // <-- this will not compile 

((Mango)fruit).wayToExposeSuperMethod(); // <-- this will output : depends upon the actual fruit 
関連する問題