私は数日前にインタビューを受けましたが、このような質問が投げられました。
Q:リンクリストを逆にします。次のコードが提供されます。
public class ReverseList {
interface NodeList {
int getItem();
NodeList nextNode();
}
void reverse(NodeList node) {
}
public static void main(String[] args) {
}
}
インターフェイスオブジェクトをメソッドパラメーターとして使用できることを知らなかったため、混乱しました。インタビュアーは少し説明しましたが、これについてはまだわかりません。誰かが私を啓発できますか?
これは実際、インターフェイスを使用する最も一般的で便利な方法の1つです。インターフェイスはコントラクトを定義し、コードは、具体的なクラスを知らなくても、インターフェイスを実装する任意のクラスで動作できます-コードが記述された時点ではまだ存在していなかったクラスでも動作できます。
Java標準API、特にコレクションフレームワークには多くの例があります。たとえば、 Collections.sort() は、List
インターフェース(ArrayList
またはLinkedList
だけでなく、独自のList
の実装は一般的ではありません)およびそのコンテンツはComparable
インターフェース(String
または数値ラッパークラス-独自のクラスにComparable
を実装させるには、quitecommon)です。
メソッドに渡されるインターフェイスの「オブジェクト」ではなく、通常のオブジェクトです。 「このパラメーターは、このインターフェイスをサポートするすべてのオブジェクトを受け入れる」という意味です。サブクラスを渡している場合でも、基本クラスタイプのオブジェクトを受け入れるのと同じです。
これは、インターフェイスへのプログラミングと呼ばれます。ノードリストの特定の実装クラスにコーディングするのではなく、これらすべての実装によって実装されるインターフェイスにコーディングします。
そうすれば、リバースメソッドを書いた後に誰かがNodeList
の新しくてより良い実装を書いて、NodeList
の新しい実装ごとにコードを適応させる必要がない場合でも、コードは機能します。 。
引数にはオブジェクトが必要です。このクラスはインターフェース(パラメーター)を実装します。
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
ラムダの学習中にこれと同じ混乱がありました。このビデオでは概念を説明しませんでしたが、インターフェイスをパラメーターとして渡すという点でどのように機能するかを理解するための明確な方法です。
インターフェイスのインスタンス(/ object)を作成することはできません。はい、インターフェイスを関数のパラメーターとして渡すことができます。しかし、質問は不完全なようです。インターフェイスはどのクラスでも実装されていません。何かが欠けています。これを実行しようとしても、コンパイラはエラーを表示しません。
ただし、reverse()メソッドでは、NodeListインターフェイスを実装するクラスのインスタンスを作成する必要があります。これが理にかなっていることを願っています。
これは可能な実装の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
匿名クラスを使用することでこの問題を解決できるかどうか知りたいです。何か案は?
インターフェースを使用する主な利点は、簡単にテストできることです。 PatientManagerと呼ばれるインターフェイスがあるとします。
「CachingPatientManager」や「LDAPPatientManager」など、想像できるものについて特定の単体テストを作成できます。ユースケースは無数にあります。
利点は、インターフェイスへのプログラミングが非常に再利用可能かつテスト可能になるためです。