2012-04-08 23 views
2

私はこのコードを、開発を中止して以来、プロジェクト用になっていた小片のフォルダに入れました。しかし、Javaの初心者は、私が持っているいくつかの質問があります(私はコードがコンパイルされていないことを認識していますが、それは私の質問の1つになります)。クラスの継承とキャスト

interface Executable { 
    public int execute (Object o); 
} 

public class Biv implements Executable { 

    public int execute (String s) { 
    System.out.println (s); 
    return s.length(); 
    } 

    public static void main (String[] args) { 
    Executable e = new Biv(); 
    System.out.println( 
     e.execute ("Hello World!")); 
    } 


} 

1)私の最初の質問は変数eに行うことです。これはExecutableオブジェクト型で宣言されていますが、新しいBivオブジェクトでインスタンス化できる理由はわかりません。何が起こっているのか、それはどういう意味ですか?

2)エラーはBivクラス内のexecuteメソッドにあります。これは、文字列ではなくオブジェクトを期待するためです。しかし、StringはObjectのサブクラスなので、ObjectをStringに置き換えることはできませんか? StringをObjectに置き換えた場合、エラーが発生する(私は思うが)現在どのように処理されているのか理解できない。

答えて

2

I don't understand why it can then be instantiated with a new Biv object

BivExecutableを実装するので、Bivの任意のインスタンスはまた、Executableのインスタンスであるため。

The error is in the execute method within the Biv class

はい、それは[Biv] execute(Object)を実装していません、です。メソッドexecute(String)は、同じシグネチャを持たないため、同じ名前を持つ別のメソッドに過ぎません。 Executableインターフェイスを実装するクラスは、execute(Object)メソッドをオーバーライドする必要があります。

安全でないため、メソッドをオーバーライドするための引数はco-varianceでJavaにありません。 e.execute(new Object())を呼び出した場合はどうなりますか? [eBivオブジェクトを参照しています] Bivは、その処理方法がわかりません。

+1

署名が必ずしも同一である必要はありません。パラメータタイプは「緩められる」ことがあります。たとえば、インタフェースのメソッドが 'String'を受け取った場合、' Biv'のメソッドに 'Object'を渡すことができます。 – Maxpm

+0

@Maxpm:それは当てはまりません。 – Natix

+0

@natix私は訂正しました。 – Maxpm

0

あなたが見ているのは、オブジェクト指向プログラムの基本概念の1つであるPolymorphismです。特定の質問#2に答えるには、インターフェイスのメソッドの型シグネチャ(引数としてオブジェクトを受け取ります)を一致させて、Stringにキャストする必要があります。しかし、この(キャスティング)はJavaではbad practiceであり、可能な限り避けるべきです。

0

あなたは(必要)Executableからメソッドをオーバーライドではありません、あなたはそれ(同じ名前、異なるパラメータの種類)をオーバーロードするです。

public class Biv implements Executable { 

    @Override // This will cause an error to be highlighted saying this isn't overriding any method 
    public int execute (String s) { 
    System.out.println (s); 
    return s.length(); 
    } 
} 
1

1)変数eはBIVが実装するインタフェースである実行可能ファイルとして宣言されています

はエラーを強調するのに役立ちます @Override注釈を使用します。これは、Bivをインスタンス化することができますが、実行可能ファイルとして格納し、実行可能ファイルとして渡すことを意味します。この変数は、実行可能ファイルとしてのみ扱えるようになりました。これは多態性です。

2)これは、関数をオーバーライドして、署名に追加の制限を追加しようとしているためです。これはLiskov置換原則に違反します。機能については、原則では、基本的に、「約束し、必要ないことを約束する」と述べています。あなたがやっていることは、インタフェースがオブジェクトであると言ったときにパラメータを強制的にStringにすることによって、「もっと必要とする」ことです。次に、これを(1)に関連付けるには、mainのExecutableオブジェクトが呼び出されたexecute()メソッドを持っている場合、execute()メソッドがObject )。

0

ObjectクラスはtoString()メソッドを実装しているため、キャストは必要ありません。 [変更のオブジェクトではなく文字列と方法で(オブジェクトのtoStringを呼び出しを受信するBIV)最初に、文字列の長さを取得:

interface Executable { 
    public int execute (Object o); 
} 

public class Biv implements Executable { 

    public int execute (Object s) { 
     System.out.println (s); 
     return s.toString().length(); 
    } 

    public static void main (String[] args) { 
     Executable e = new Biv(); 
     System.out.println( 
      e.execute ("Hello World!")); 
    } 

} 

しかし、コマンドデザインパターンを実装するために、一般的に悪い習慣ですいくつかのタイプの可能なパラメータを受け入れるメソッドを持つためにObjectを使用します。 Parameterインタフェースの後ろにパラメータをカプセル化することが最善の方法です。

0

まず者は、この行を考えてみましょう:

public class Biv implements Executable

implements Executableは、クラスBivExecutableの役割を取ることができることを示しています。別の言い方をすると、にはすべてのメソッドの実装がExecutableにあります。

これは後で、あなたがこれを行うことができる理由を説明します。

Executable e = new Biv();

私はタイプExecutableの変数を持っており、この機会に、私はそれのBiv実装を使用するつもりです。 BivExecutableインターフェイスを実装している場合(そして、あなたの例ではそれが宣言されている場合)、これは問題ありません。

ここで、この例で問題が発生し始めるところを見てみましょう。実行ファイル内のインタフェースは、このメソッドdeclartionが含まれています

public int execute (Object o);

これは、あなたがexecuteを呼び出して、あなたが好きな、絶対に任意のObjectを渡すことができ、述べています。しかしBizexecuteメソッドに好きなオブジェクトを渡すことはできますか?いいえ、Stringにしか渡すことはできません。だからBizは完全にインターフェイスを満たしていません。

[円の楕円形の問題]は、さらに読むことをお勧めします。 1