interface en tant que paramètre de méthode en Java

J'ai eu une interview il y a quelques jours et on m'a posé une question comme celle-ci.

Q: Inverser une liste liée. 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 savais pas qu'un objet d'interface pouvait être utilisé comme paramètre de méthode. L'intervieweur a expliqué un peu mais je ne suis toujours pas sûr à ce sujet. Quelqu'un pourrait m'éclairer?

37
demandé sur nIcE cOw 2010-04-04 22:21:43

8 réponses

C'est en fait l'une des plus courantes et les plus utiles manières 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 lorsque le code a été écrit.

Il existe de nombreux exemples dans L'API Java standard, en particulier dans le framework collections. Par exemple, Collections.sort () peut trier tout ce qui implémente le List interface (pas seulement ArrayList ou LinkedList, bien que l'implémentation de votre propre List soit rare) et dont le contenu implémente l'interface Comparable (pas seulement String ou les classes wrapper numériques-et avoir votre propre classe implémenter Comparable à cette fin est assez commun).

54
répondu Michael Borgwardt 2013-10-24 01:33:19

Ce n'est pas l'interface "objet" qui est passée à la méthode, mais juste un objet normal. C'est juste une façon de dire "ce paramètre acceptera tout 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.

19
répondu Ben Zotto 2010-04-04 18:28:04

C'est ce qu'on appelle la programmation aux interfaces. Vous ne codez pas sur une classe d'implémentation spécifique de listes de nœuds mais sur l'interface implémentée par toutes ces implémentations.

De cette façon, votre code fonctionnera toujours si quelqu'un écrit une nouvelle et bien meilleure implémentation de NodeList après avoir écrit votre méthode inverse et vous n'avez pas à adapter votre code pour chaque nouvelle implémentation de NodeList.

8
répondu ahe 2018-08-05 09:13:03

L'argument a besoin d'un objet dont la 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.");
}

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

6
répondu Pindatjuh 2010-04-04 18:33:46

Avait cette même confusion en apprenant des trucs lambda. Cette vidéo n'a pas expliqué le concept, mais c'est un moyen clair pour vous de voir comment cela fonctionne en termes de passage d'une interface en tant que paramètre.

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

2
répondu Yoho 2018-01-24 06:41:15

Le principal avantage de l'utilisation des interfaces, à mon humble avis, est de pouvoir tester facilement. Supposons que vous ayez 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 myriad.

L'avantage est que la programmation À l'interface devient hautement réutilisable et testable.

1
répondu Nirmal 2015-04-12 03:17:53

Vous ne pouvez pas créer une instance (objet ) d'une Interface. Oui, vous pouvez passer L'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. Il manque quelque chose. 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.

1
répondu user4660857 2016-02-14 01:29:06

C'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?

1
répondu jrook 2016-09-19 01:56:14