3

インターフェースをいじってみると、よくわからないことがあるので質問があります。

次のコードは実行されません。これは、インターフェイスメソッドが任意のオブジェクトに対して機能するメソッドを必要とし、実装されたメソッドの署名が文字列オブジェクトのみを許可するように変更されているため、私が期待する動作です。

interface I {
    public void doSomething(Object x);
}

class MyType implements I {
    public void doSomething(String x) {
        System.out.println(x);
    }
}

しかし、次のコードブロックを使用して、それが機能するのを見てショックを受けました。オブジェクトを返すことを期待しているので、それは機能しないと思いました。実装されたメソッドは文字列オブジェクトのみを返します。これが機能する理由と、渡されたパラメーターと戻り値の2つの原則の違いは何ですか?

interface I {
    public Object doSomething(String x);
}

class MyType implements I {
    public String doSomething(String x) {
        System.out.println(x);
        return(x); 
    }
}
4

8 に答える 8

3
public Object doSomething(String x);

何かを返さなければなりません。実際、それが何らかの種類のオブジェクトである限り、何でも。したがって、実装する場合

public String doSomething(String x) {stuff}

実際にはオブジェクトを返すので、それは問題ありません。返されるオブジェクトが常に文字列になるという事実は大したことではありません。

最初の例が機能しない理由は、文字列のみを受け入れる方が、オブジェクトを受け入れるよりも制限が厳しいためです。ただし、文字列のみを返すことは問題ありません。

例えとして、あなたが建物を塗装する契約を結んでいて、あなたを助けるために何人かの従業員を雇うつもりだとしましょう。契約では、身長に関係なく、応募する画家を雇う必要がありますが、使用する色の絵の具は指定されていません。高さ6フィートを超える画家のみを雇った場合(これが入力であり、すべてのオブジェクトではなく文字列のみを受け入れます)、契約に違反することになります。ただし、契約では色が指定されておらず、建物をペイントする必要があるだけなので、青いペイントのみ(文字列のみを返す)でペイントすることを選択しても問題ありません。

于 2012-05-14T15:57:09.847 に答える
2

Stringaは。なので機能しObjectます。

于 2012-05-14T15:53:04.827 に答える
2

Java言語仕様から:

戻り型が参照型である場合、戻り型は相互にオーバーライドするメソッド間で異なる場合があります。return-type-substututabilityの概念は、共変リターン、つまり、リターンタイプのサブタイプへの特殊化をサポートします。

つまり、これは同じように機能しますが、インターフェイスの戻り型がStringであり、実装クラスがObjectの場合は機能しません。

于 2012-05-14T15:55:11.450 に答える
2

この動作の背後にある原理は、共変リターンタイプと呼ばれます。この特定のケースでは、オーバーライドするタイプは、最初に宣言されたパラメータータイプを「狭める」可能性があります。

これは、Stringサブクラス化と同様Objectに、Objectをで置き換えることができることを意味しStringます。

于 2012-05-14T15:57:28.603 に答える
2

これは、JavaSE5.0で導入された共変リターンタイプと関係があります。詳細については、 http://docs.oracle.com/javase/tutorial/java/javaOO/returnvalue.html
を参照してください。

于 2012-05-14T16:07:09.397 に答える
1

最初の例が機能せず、2番目の例が機能する理由は、関数プロトタイプが名前とすべてのパラメーターのみで定義され、戻り型では定義されていないためです。最初の例では違いがあるため、コンパイラーはそれらを2つの異なる関数であると見なします。

2番目の例では、実装された関数は型を拡張せず、代わりに型を特殊化するため(StringはObjectの特殊化です)、機能します。

同様に、実装されたメソッドの可視性を制限することはできますが、拡大することはできません。

さらに、Javaにはジェネリックスがあり、このコンテキストで役立ちます。

例:

interface I<T>
{
    public void doSomething(T x);
}

class MyType implements I<String>
{
    public void doSomething(String x)
    {
        System.out.println(x);
    }
}
于 2012-05-14T15:55:26.483 に答える
1

メソッドシグネチャはリターンタイプを考慮しません。(ただし、シグネチャは同じでリターンタイプが異なる2つのメソッドを宣言するのはエラーです)。それで:

void doSomething(Object)
void doSomething(String)

単に2つのメソッドであり、他のメソッドをオーバーライドまたは実装するものはありません

于 2012-05-14T15:55:47.503 に答える
1

文字列クラスはオブジェクトクラスから継承されるため、このコードのみが機能します。

于 2012-05-14T15:59:26.030 に答える