2016-06-23 13 views
0

私が持っているクラスAのように:Javaはオーバーライドの場合は戻り値の型を変更することはできませんなぜ

public class A { 
    int sayHello(int i,int j){ 
     return i+j; 
    } 
} 

別のクラスBのように:

public class B extends A { 
    @Override 
    int sayHello(int i, int j) { 
     return i+j; 
    } 
} 

私は方法のsayHelloの戻り値の型を変更した場合クラスAのint(int、int)をintからfloatに変更すると、オーバーライドルールの戻り型も考慮されるため、オーバーライドおよびオーバーロードの有効な理由がないため、エラーが表示されます。

私はと混同しています。なぜ、javaはreturntypeを変更できないのですか? method()リターンを何

class Parent { 
    int method() { return 1; } 
} 

class Child extends Parent { 
    float method() { return 1.0f; } 
} 

Parent p = new Child(); 
int myInt = p.method(); 

:なぜ型を返すためにも

+0

多型を許可することは、検出困難なバグを作成する大きな理由です。次に、 'int blub = myInterfaceTypeのようなものです。getIntFromImplementedType() 'は安全ではありません。なぜなら、' int'だけでなく何も返すことができないからです。 – Tom

答えて

1

あなた戻り値の型を変更することができます。それだけで共変タイプでオーバーライドする必要があります。あなたのようなインタフェースを定義した場合

たとえば、:

interface Foo { 
    Object foo(); 
} 

、このようにそれを実装するために細かいです:

class Bar implements Foo { 
    @Override public String foo() { 
    return ""; 
    } 
} 

Foo.foo()のすべての実装がObjectを返さなければならないため、すべてのString sはObjectです。

しかし、あなたは他の方法でラウンドそれを行うことができませんでした:Foo.foo()の戻り値の型がStringた場合、このメソッドの呼び出し元がStringを起動できるようにする必要があるので、あなたは '、Objectを返すようにそれを実装できませんでしたそのインスタンスのメソッドを返します。例えば:Objectにはlength()方法がないようObjectは、返された場合

void test(Foo instance) { 
    System.out.println(instance.foo().length()); 
} 

これは、実行時に動作しないでしょう。 (具体的には、のいずれかの長さのメソッドではなく、String.length()メソッドでなければなりません。Javaではダックタイピングをサポートしていません)。コンパイラはこの不一致を検出することができます。

何の種類がありませんがint(またはそのことについては、プリミティブ型、)で共変なので、あなたがintを返すメソッドをオーバーライドするときintを返すことがあります。


これは許容される理由を理論的な理由は、「サブタイプの方法は、彼らが受け入れるパラメータのより一般的な、そして、彼らは戻り値の型で、より特異的であることができる」と言い換えることができLiskov Substitution Principle、です。

Java では、メソッドのオーバーロードを解決するために、より一般的なパラメータ型を使用できます。

6

同じにする必要がありますか? Parentはそれがintであるため、intである必要があります。しかし、Childfloatを返します。だから何が起こると思いますか? JVMがちょうどクラッシュすべきか?

ところで、は戻り値の型を変更しますが、型のサブタイプでなければなりません。オーバーライドされたメソッドが返されます。だからParentを返し、返品タイプとしてChildを返すメソッドをオーバーライドしてとすることができます。

0

示すhere(強調私自身の)

としてメソッドをオーバーライドするサブクラスの能力は、その動作が「十分近い」され、その後、スーパークラスから へ 継承するクラスのように動作を変更できます必要です。 オーバーライドするメソッドは、同じ名前の の数と型のパラメータを持ち、 オーバーライドするメソッドとして戻り値の型を持ちます。オーバーライドされたメソッドは、オーバーライドされたメソッドによって返されたタイプ のサブタイプも返すことができます。このサブタイプは、共変量 リターンタイプと呼ばれます。

戻り値の型が同じでない場合は、多態性を使用して実行時にクラスの型を検出する可能性のある他のクラスのものが破損します。

0

基本的に、Javaはこれが(非常に正しく、私は...だと思う)と考えています。は、コンパイル時に役立つ厄介なバグです!

子孫-クラスとオーバーライドの背後にある基本的な考え方は、彼らがいる限り、それはそれのそれis anインスタンスことが知られているように対処されるかもしれない特定のクラスインスタンスの“味”これまでのように、発信者が心配する必要はないということですクラスまたはその子孫の1つです。  の根底実装が特定のクラスはないプロトタイプを変化させる可能性があるため、コンパイラはまた、信頼性の高いコードを生成することができる: 各インスタンスはが同じデータ型を返し、同じ方法、-N-Dを有するであろう。

特殊なケースで別のデータ型を返す必要がある場合は、そのためにカスタムメソッドを定義する必要があります。  これは(!)あなたに従う様々なプログラマーにとっても重要です。あなたのコードが異なる何かをする場合 (“そのパン・トラックについて残念... ” など)  は、それは非常に-著しくは、アプリケーションのソースコードに異なるになります!

は覚えておいてください: をJavaは、実際にあなたがこの種のものを行うには許可されている場合、あなたは知らず知らずのうち NAS-SSS-sstyバグ既存のどの部分で、“はデバッグ、”コード、どこでもでの導入可能性があります(!)あなたの間違いなく広大なアプリケーション、ちょうど“あなたの特別なケースのインスタンスにつまずくために起こった。あなたがメソッドをオーバーライドするとき”

関連する問題