87 votes

Collision de nom de méthode dans l'implémentation d'interface - Java

Si j'ai deux interfaces , tous deux sont très différents dans leur application , mais avec la même signature de la méthode , comment puis-je faire une classe implémente à la fois sans être forcé à écrire une seule méthode qui sert à la fois les interfaces et l'écriture de logique alambiquée dans l'implémentation de la méthode qui vérifie que le type de l'objet de l'appel est effectué, et invoquer bon code ?

En C# , il est surmonté par ce qui est appelé comme l'explicite l'implémentation de l'interface. Est-il équivalent moyen en Java ?

73voto

jjnguy Points 62123

Non, il n'y a aucun moyen d'implémenter la même méthode de deux manières différentes dans une même classe en Java.

Cela peut conduire à de nombreuses situations confuses, raison pour laquelle Java ne l’a pas autorisé.

 interface ISomething {
    void doSomething();
}

interface ISomething2 {
    void doSomething();
}

class Impl implements ISomething, ISomething2 {
   void doSomething() {} // There can only be one implementation of this method.
}
 

Ce que vous pouvez faire est de composer une classe sur deux classes qui implémentent chacune une interface différente. Ensuite, cette classe aura le comportement des deux interfaces.

 class CompositeClass {
    ISomething class1;
    ISomething2 class2;
    void doSomething1(){class1.doSomething();}
    void doSomething2(){class2.doSomething();}
}
 

13voto

gustafc Points 13552

Il n'y a pas de véritable moyen de résoudre cela en Java. Vous pouvez utiliser les classes internes comme une solution de contournement:

interface Alfa { void m(); }
interface Beta { void m(); }
class AlfaBeta implements Alfa {
    private int value;
    public void m() { ++value; } // Alfa.m()
    public Beta asBeta() {
        return new Beta(){
            public void m() { --value; } // Beta.m()
        };
    }
}

Bien qu'il n'autorise pas pour des distributions d' AlfaBeta de Beta, downcasts sont généralement mauvais, et si l'on peut s'attendre à ce que l' Alfa instance a souvent un Beta aspect, trop, et pour une raison quelconque (généralement de l'optimisation est la seule raison valable), vous voulez être en mesure de le convertir en Beta, vous pourriez faire une sous-interface de l' Alfa avec Beta asBeta() .

11voto

Michael Aaron Safyan Points 45071

Si vous rencontrez ce problème, il est plus probable parce que vous êtes à l'aide de l'héritage où vous devriez être à l'aide de la délégation. Si vous avez besoin de fournir deux différents, mais similaires, interfaces pour le même modèle sous-jacent de données, alors vous devriez utiliser une vue à moindre coût à fournir l'accès aux données à l'aide d'une autre interface.

Pour donner un exemple concret pour le dernier cas, supposons que vous souhaitez mettre en œuvre tant de la Collecte et MyCollection (qui n'hérite pas de la Collecte et a une interface incompatible). Vous pouvez fournir une "Collection getCollectionView()" et "MyCollection getMyCollectionView()" des fonctions qui offrent un peu de poids à la mise en œuvre de la Collecte et MyCollection, en utilisant les mêmes données sous-jacentes.

Pour le premier cas... supposons que vous voulez vraiment un tableau d'entiers et un tableau de chaînes de caractères. Au lieu d'hériter de deux de la Liste<Integer> et List<String>, vous devriez avoir un membre de type List<Integer> et un autre membre de type List<String>, et reportez-vous aux membres, plutôt que d'essayer d'hériter de deux. Même si vous avez seulement besoin d'une liste d'entiers, il est préférable d'utiliser de la composition ou de la délégation sur l'héritage dans ce cas.

1voto

tiancheng Points 21

Le "classique" Java problème affecte également mon développement Android...
La raison semble être simple:
Plus de cadres et de bibliothèques que vous avez à utiliser, plus facilement les choses peuvent être hors de contrôle...

Dans mon cas, j'ai un BootStrapperApp classe héritée de android.app.L'Application,
alors que la même classe doit également mettre en œuvre une Plate-forme de l'interface d'un framework MVVM afin d'être intégrées.
Méthode collision s'est produite sur un getString() la méthode, qui est annoncé par les deux interfaces et devrait avoir differenet mise en œuvre dans différents contextes.
La solution de contournement (laid..OMI) à l'aide d'un intérieur de classe pour mettre en œuvre toutes les Plate-forme de méthodes, tout simplement parce que d'un mineur, signature de la méthode du conflit...dans certains cas, ces emprunté la méthode est même pas utilisé, mais affecté majeur de la conception de la sémantique).
Je suis plutôt d'accord C#-style de contexte explicite/espace de noms indication est utile.

1voto

notAtAll Points 1

La seule solution qui est venu dans mon esprit, c'est à l'aide de referece objets à celui que vous voulez implent muliple interfaceces.

par exemple: supposons que vous avez 2 interfaces à mettre en œuvre

public interface Framework1Interface {

    void method(Object o);
}

et

public interface Framework2Interface {
    void method(Object o);
}

vous pouvez les joindre en deux Facador objets:

public class Facador1 implements Framework1Interface {

    private final ObjectToUse reference;

    public static Framework1Interface Create(ObjectToUse ref) {
        return new Facador1(ref);
    }

    private Facador1(ObjectToUse refObject) {
        this.reference = refObject;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Framework1Interface) {
            return this == obj;
        } else if (obj instanceof ObjectToUse) {
            return reference == obj;
        }
        return super.equals(obj);
    }

    @Override
    public void method(Object o) {
        reference.methodForFrameWork1(o);
    }
}

et

public class Facador2 implements Framework2Interface {

    private final ObjectToUse reference;

    public static Framework2Interface Create(ObjectToUse ref) {
        return new Facador2(ref);
    }

    private Facador2(ObjectToUse refObject) {
        this.reference = refObject;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Framework2Interface) {
            return this == obj;
        } else if (obj instanceof ObjectToUse) {
            return reference == obj;
        }
        return super.equals(obj);
    }

    @Override
    public void method(Object o) {
        reference.methodForFrameWork2(o);
    }
}

À la fin de la classe que tu voulais quelque chose comme

public class ObjectToUse {

    private Framework1Interface facFramework1Interface;
    private Framework2Interface facFramework2Interface;

    public ObjectToUse() {
    }

    public Framework1Interface getAsFramework1Interface() {
        if (facFramework1Interface == null) {
            facFramework1Interface = Facador1.Create(this);
        }
        return facFramework1Interface;
    }

    public Framework2Interface getAsFramework2Interface() {
        if (facFramework2Interface == null) {
            facFramework2Interface = Facador2.Create(this);
        }
        return facFramework2Interface;
    }

    public void methodForFrameWork1(Object o) {
    }

    public void methodForFrameWork2(Object o) {
    }
}

vous pouvez maintenant utiliser les getAs* des méthodes pour "exposer" de votre classe

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X