2 votes

Pourquoi ne peut-on pas stocker un objet de type <ParentInterface> dans un conteneur de type <ChildInterface> en Java ?

J'ai créé une interface :

MyList<E> extends List<E>{
...
}

Cependant, lorsque j'essaie de le faire : MyList<_MyClass> = new LinkedList<_MyClass>() Je reçois une erreur du compilateur.

Si MyList possède par définition toutes les méthodes de List pourquoi ne puis-je pas l'attribuer ? Si j'essaie de l'assigner, j'obtiens une exception d'exécution.

Qu'est-ce que je manque ?

EDIT. Merci pour toutes les réponses. Je pensais que l'on pouvait utiliser ceci en conjonction avec les nouvelles méthodes par défaut de la version 1.8 pour créer quelque chose comme les méthodes d'extension de C#. Par exemple, MyList a un tas de méthodes par défaut pour travailler sur List (et aucune autre), mais je vois maintenant pourquoi c'est conceptuellement impossible.

3voto

Teto Points 440

Pensez-y en termes d'interface plus facile.

Supposons que la bibliothèque de base dispose d'une interface pour Animal. Et une implémentation appelée Dog. C'est-à-dire que Dog implémente Animal.

Vous créez maintenant une nouvelle implémentation d'Animal appelée Human.

L'homme met également en œuvre l'animal.

Je peux donc maintenant le faire.

Animal  a1, a2;
a1 = new Dog();
a2 = new Human();

Mais je ne peux PAS faire cela.

Human h = new Dog();

Certes, les humains et les chiens sont des animaux, mais un chien ne peut en aucun cas remplacer un humain. Il s'agit d'une exception à la compilation.

Le cas est maintenant un peu plus complexe.

List est l'interface principale, et l'implémentation de base est LinkedList. En d'autres termes, LinkedList implémente List.

En prolongeant mon analogie, vous avez donc créé une nouvelle classe appelée HumanList qui étend également List.

Donc, en répétant ce que j'ai fait précédemment, vous pouvez le faire.

List<String>  b1, b2;

b1 = new LinkedList<String>;
b2 = new HumanList<String>;

Mais vous ne pouvez pas le faire.

HumanList<String> = new LinkedList<String>.

Bien sûr, HumanList et LinkedList sont toutes deux des implémentations de List. Mais une LinkedList ne peut pas remplacer une HumanList dans toutes les situations.

En effet, votre implémentation de HumanList peut, en plus de l'interface List, avoir d'autres méthodes telles que displaySocialSecurityNumbers().

Si votre HumanList n'a pas d'autres méthodes que List, et que vous n'en aurez jamais besoin, vous pouvez faire ce qui suit.

List<E>  b2 = new HumanList<E>();

Enfin, comme l'a déjà suggéré Xgord, si vous voulez suggérer que votre HumanList est un type de LinkedList, alors vous devriez faire en sorte que HumanList étende LinkedList.

2voto

xgord Points 2285

Cela s'explique par le fait que MyList objets ne sont pas de type LinkedList c'est-à-dire ce que vous attribuez.

Les deux MyList y LinkedList étendre List , ce qui les rend tous les deux List les objets de type. En affectant des objets de type MyList<_MyClass> = new LinkedList<_MyClass>() Cependant, vous affirmez qu'un LinkedList est un objet MyList ce qui n'est pas le cas.

Changez votre classe en :

MyList<E> extends LinkedList<E>{
...
}

et cela devrait fonctionner.

Editer

Je viens de me rendre compte que j'ai également été victime du piège Is-A. Si vous faites MyList<E> extends LinkedList<E> Vous devrez alors échanger votre affectation contre un autre : LinkedList<_MyClass> x = new MyList<_MyClass>()

1voto

Yogesh_D Points 452

Pour ajouter à ce qu'a dit @Teto, cela brisera la Principe de substitution de Liskov

La substituabilité est un principe du programme orienté objet. qui stipule que, dans un programme informatique, si S est un sous-type de T, alors les objets de type T peuvent être remplacés par des objets de type S (c'est-à-dire qu'un objet du type T peut être remplacé par son objet de sous-type du type type S) sans altérer aucune des propriétés souhaitables de ce programme programme (correction, tâche exécutée, etc.).

Dans votre cas, MyList peut ajouter un comportement qui ne fait pas partie de la List et ne fera donc pas partie de la LinkedList . C'est ainsi que LinkedList ne peut être remplacé par MyList

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