2010-04-04 7 views
32

J'ai eu une interview il y a quelques jours et a été lancé une question comme celle-ci.interface comme un paramètre de méthode en Java

Q: Inverse une liste chaînée. Le code suivant est donné:

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

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

    } 
} 

J'étais confus parce que je ne connaissais pas un objet d'interface qui pourrait être utilisé comme paramètre de méthode. L'intervieweur a expliqué un peu mais je ne suis toujours pas sûr de cela. Quelqu'un pourrait-il m'éclairer?

Répondre

52

C'est en fait l'une des façons les plus courantes et les plus utiles d'utiliser une interface. L'interface définit un contrat, et votre code peut fonctionner avec n'importe quelle classe qui implémente l'interface, sans avoir à connaître la classe concrète - il peut même fonctionner avec des classes qui n'existaient pas encore lors de l'écriture du code.

Il existe de nombreux exemples dans l'API standard Java, en particulier dans la structure des collections. Par exemple, Collections.sort() peut trier tout ce qui implémente l'interface List (pas seulement ArrayList ou LinkedList, bien que la mise en œuvre de votre propre List est rare) et dont le contenu implémenter l'interface Comparable (pas seulement String ou les classes d'emballage numérique - et avoir votre propre classe implémente à cette fin est tout à fait commun).

+0

Merci Mike! L'exemple de liste est vraiment instructif et facile à comprendre. – zihaoyu

6

L'argument nécessite un objet, quelle classe implémente une interface (le paramètre).

Dans pseudo Java le code:

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

est égal à:

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

Remarque; En savoir plus sur Interfaces ici: http://java.sun.com/docs/books/tutorial/java/IandI/interfaceAsType.html

+8

Le paramètre * * est un type d'interface, l'argument * * est un objet skaffman

+3

Et pour être vraiment bien un pedent. L'argument est une référence à un objet:} –

+0

+1 pour le lien du tutoriel cogent. – trashgod

19

Ce n'est pas l'interface "objet" qui est passée à la méthode, toujours juste un objet régulier. C'est juste une façon de dire "ce paramètre acceptera n'importe quel objet qui supporte cette interface". Cela équivaut à accepter un objet d'un type de classe de base, même si vous passez une sous-classe.

+0

Super, aidé !! : D – roottraveller

7

Ceci est appelé programmation aux interfaces. Vous ne codez pas vers une classe d'implémentation spécifique de listes de nœuds mais vers l'interface implémentée par toutes ces implémentations. De cette façon, votre code fonctionnera encore si quelqu'un écrit une nouvelle et bien meilleure implémentation de NodeList après avoir écrit votre méthode inverse et que vous n'avez pas besoin d'adapter votre code pour chaque nouvelle implémentation de NodeList.

1

Le principal avantage de l'utilisation d'interfaces, à mon humble avis, est de pouvoir tester facilement. Supposons que vous avez une interface appelée PatientManager.

Vous pouvez écrire des tests unitaires spécifiques pour des choses imaginables comme "CachingPatientManager" ou "LDAPPatientManager", le cas d'utilisation pourrait être myriade. L'avantage est que la programmation à l'interface devient hautement réutilisable et testable.

1

Vous ne pouvez pas créer une instance (/ objet) d'une interface. Oui, vous pouvez passer Interface en tant que paramètre dans la fonction. Mais la question semble incomplète.L'interface n'est implémentée par aucune classe. Quelque chose manque. Si vous essayez d'exécuter ceci, le compilateur ne montrera aucune erreur. Mais, dans la méthode reverse(), vous devez créer une instance de classe qui implémente l'interface NodeList. J'espère que cela a du sens.

0

Ceci est une implémentation possible:

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()); 
     } 
} 

sortie du programme:

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

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

Je suis très curieux de savoir si ce problème peut être résolu en utilisant une classe anonyme. Des idées? Avait cette même confusion tout en apprenant des choses lambda.

Questions connexes