web-dev-qa-db-ja.com

Java

私は数日前にインタビューを受けましたが、このような質問が投げられました。

Q:リンクリストを逆にします。次のコードが提供されます。

public class ReverseList { 
    interface NodeList {
        int getItem();
        NodeList nextNode();
    }
    void reverse(NodeList node) {

    }
    public static void main(String[] args) {

    }
}

インターフェイスオブジェクトをメソッドパラメーターとして使用できることを知らなかったため、混乱しました。インタビュアーは少し説明しましたが、これについてはまだわかりません。誰かが私を啓発できますか?

44
zihaoyu

これは実際、インターフェイスを使用する最も一般的で便利な方法の1つです。インターフェイスはコントラクトを定義し、コードは、具体的なクラスを知らなくても、インターフェイスを実装する任意のクラスで動作できます-コードが記述された時点ではまだ存在していなかったクラスでも動作できます。

Java標準API、特にコレクションフレームワークには多くの例があります。たとえば、 Collections.sort() は、Listインターフェース(ArrayListまたはLinkedListだけでなく、独自のListの実装は一般的ではありません)およびそのコンテンツはComparableインターフェース(Stringまたは数値ラッパークラス-独自のクラスにComparableを実装させるには、quitecommon)です。

59

メソッドに渡されるインターフェイスの「オブジェクト」ではなく、通常のオブジェクトです。 「このパラメーターは、このインターフェイスをサポートするすべてのオブジェクトを受け入れる」という意味です。サブクラスを渡している場合でも、基本クラスタイプのオブジェクトを受け入れるのと同じです。

24
Ben Zotto

これは、インターフェイスへのプログラミングと呼ばれます。ノードリストの特定の実装クラスにコーディングするのではなく、これらすべての実装によって実装されるインターフェイスにコーディングします。

そうすれば、リバースメソッドを書いた後に誰かがNodeListの新しくてより良い実装を書いて、NodeListの新しい実装ごとにコードを適応させる必要がない場合でも、コードは機能します。 。

8
ahe

引数にはオブジェクトが必要です。このクラスはインターフェース(パラメーター)を実装します。

InpseudoJavaコード:

void reverse(NodeList node) {
    // your code
}

等しい:

reverse(x) {
    if(x == null || x instanceof NodeList) {
         // your code
    }else throw new RuntimeException("Some sort of error.");
}

注意;インターフェイスの詳細については、こちらをご覧ください。 http://Java.Sun.com/docs/books/tutorial/Java/IandI/interfaceAsType.html

6
Pindatjuh

ラムダの学習中にこれと同じ混乱がありました。このビデオでは概念を説明しませんでしたが、インターフェイスをパラメーターとして渡すという点でどのように機能するかを理解するための明確な方法です。

https://www.youtube.com/watch?v=mk3erzL70yM

2
Yoho

インターフェイスのインスタンス(/ object)を作成することはできません。はい、インターフェイスを関数のパラメーターとして渡すことができます。しかし、質問は不完全なようです。インターフェイスはどのクラスでも実装されていません。何かが欠けています。これを実行しようとしても、コンパイラはエラーを表示しません。

ただし、reverse()メソッドでは、NodeListインターフェイスを実装するクラスのインスタンスを作成する必要があります。これが理にかなっていることを願っています。

1
user4660857

これは可能な実装の1つです。

public class ReverseList { 
interface NodeList {
    int getItem();
    NodeList nextNode();
}

static class Node implements NodeList {
    private int item;
    private Node next;

    @Override
    public int getItem() {
        return item;
    }

    public void setItem(int si) {
        item = si;
    }

    @Override
    public NodeList nextNode() {
        return this.next;
    }

    public void setNext(Node n) {this.next=n;}

}

Node reverse(NodeList head) {
    Node node = (Node) head;
    Node previous = null;
    while(node.nextNode() !=null) {
        Node tempNext = (Node) node.nextNode();
        node.setNext(previous);
        previous = node;
        node = tempNext;
    }
    node.setNext(previous);
    return node;

}
public static void main(String[] args) {
    //Initialization block
    ReverseList rl = new ReverseList();
    Node n1= new Node(); n1.setItem(1);
    Node n2=new Node(); n2.setItem(2);
    Node n3 =new Node(); n3.setItem(3);
    n1.setNext(n2); n2.setNext(n3); n3.setNext(null);

    //Reversing the list
    System.out.println("Before reversal");      
    System.out.println(n1.getItem() +"->" 
                    + n1.nextNode().getItem() + "->"
                    + n1.nextNode().nextNode().getItem() + "->"
                    +n1.nextNode().nextNode().nextNode());


    rl.reverse(n1);

    System.out.println("\nAfter reversal");
    System.out.println(n3.getItem() +"->" 
            + n3.nextNode().getItem() + "->"
            + n3.nextNode().nextNode().getItem() + "->"
            +n3.nextNode().nextNode().nextNode());
        }
}

プログラム出力:

Before reversal
1->2->3->null

After reversal
3->2->1->null

匿名クラスを使用することでこの問題を解決できるかどうか知りたいです。何か案は?

1
jrook

インターフェースを使用する主な利点は、簡単にテストできることです。 PatientManagerと呼ばれるインターフェイスがあるとします。

「CachingPatientManager」や「LDAPPatientManager」など、想像できるものについて特定の単体テストを作成できます。ユースケースは無数にあります。

利点は、インターフェイスへのプログラミングが非常に再利用可能かつテスト可能になるためです。

1
Nirmal