3 votes

Renvoi de la sous-classe de la superclasse générique dans une méthode de la superclasse

Je suis nouveau dans le domaine de Java et je viens d'un environnement PHP, alors je suis désolé si cela est évident. J'essaie d'implémenter une classe d'arbre binaire et j'ai créé une ADT comme suit :

public abstract class BTree<T> {
    private T value;
    private BTree<T> leftChild;
    private BTree<T> rightChild;
    private BTree<T> parent;
    public BTree<T> getLeftChild() { return this.leftChild; }
    ....
} 

Puis j'ai une autre classe qui l'étend comme ceci :

public class BIntTree extends BTree<Integer> {
}

Cependant, j'aimerais pouvoir intégrer à BIntTree une méthode permettant d'appeler this.getLeftChild(); et obtenir en retour une instance de BIntTree plutôt qu'une instance de BTree<Integer>

Est-ce possible en définissant la classe/méthode générique ou dois-je explicitement utiliser le type cast après avoir utilisé this.getLeftChild() ou même surcharger la méthode de la superclasse ?

La solution que j'ai trouvée est d'effectuer un typage explicite dans la méthode BIntTree avec la commande BIntTree b=(BIntTree) this.getLeftChild(); ce qui me semble désordonné.

De plus, je ne suis pas sûr de ce qui se passerait si j'avais défini ce type de casting et que getLeftChild() retournait null, est-ce qu'une exception serait levée ? Si oui, comment puis-je y remédier étant donné que null est également une valeur valide si elle existe ?

4voto

Mark Peters Points 42201

Il est possible d'avoir une classe auto-typée, mais il faut se demander pourquoi on la veut. Pourquoi avez-vous besoin de savoir qu'il s'agit d'une classe BIntTree plutôt qu'un BTree<Integer> ? Que vous a apporté l'utilisation des génériques ?

Quoi qu'il en soit, vous pourriez faire quelque chose comme ça :

public abstract class BTree<V, T extends BTree<V, T>> {
    public T getLeft() {...}
    public T getRight() {...}
    public V getValue() {...}
}

Alors votre BIntTree serait

public class BIntTree extends BTree<Integer, BIntTree> {
    //...
}

Editar

En ce qui concerne votre question sur le moulage null rien ne vous empêche de tester vous-même ce comportement. Mais pour répondre à votre question, il est sûr de lancer null à n'importe quel type.

1voto

Mansoor Siddiqui Points 5910

Tout d'abord, j'imagine que vous voudriez faire value , leftChild , rightChild y parent protégées, et non privées, afin qu'elles soient accessibles depuis la sous-classe.

Une fois que vous avez fait ce changement, vous pouvez avoir BIntTree.getLeftChild() retourner un BTree<Integer> en définissant simplement votre sous-classe comme suit :

public class BIntTree extends BTree<Integer> {
    public BTree<Integer> getLeftChild() { return this.leftChild; }
    ...
}

J'ajouterai simplement que vous ne devriez vraiment définir une telle classe que si vous avez un peu de Integer -Une logique spécifique se produit ici. Sinon, il serait logique de laisser le type de T pour quiconque utilise votre BTree classe.

1voto

Igor Nikolaev Points 702

Vous pouvez surcharger la méthode requise comme ceci :

public class BIntTree extends BTree<Integer> {
    @Override
    public BIntTree getLeftChild() { return (BIntTree) super.getLeftChild(); } 
}

Depuis la version 1.5, Java prend en charge les types de retour covariants, ce qui signifie que vous pouvez retourner le type avec sa sous-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