Java; casting de la classe de base de la classe dérivée
Pourquoi ne puis-je pas jeté une classe de base instance d'une classe dérivée?
Par exemple, si j'ai une classe B qui s'étend d'une classe C, pourquoi ne puis-je pas le faire?
B b=(B)(new C());
ou cela?
C c=new C();
B b=(B)c;
Bien, permettez-moi d'être plus précis quant à ce que je suis en train de faire. Voici ce que j'ai:
public class Base(){
protected BaseNode n;
public void foo(BaseNode x){
n.foo(x);
}
}
public class BaseNode(){
public void foo(BaseNode x){...}
}
Maintenant, je veux créer un nouvel ensemble de classes qui s'étendent de la Base et Basenode, comme ceci:
public class Derived extends Base(){
public void bar(DerivedNode x){
n.bar(x);//problem is here - n doesn't have bar
}
}
public class DerivedNode extends BaseNode(){
public void bar(BaseNode){
...
}
}
Donc, essentiellement, je veux ajouter de nouvelles fonctionnalités à la Base et aux BaseNode en les étendant à la fois, et d'ajouter une fonction à la fois d'entre eux. En outre, la Base et la BaseNode devrait être en mesure d'être utilisé sur leur propre.
J'aimerais vraiment le faire sans les génériques si possible.
Bon alors j'ai fini par essayer de le comprendre, en partie grâce à Maruice Perry réponse.
Dans mon constructeur pour Base
, n
est instancié comme un BaseNode
. Tout ce que j'avais à faire était de ré-instancier n
comme un DerivedNode
dans ma classe dérivée dans le constructeur, et il fonctionne parfaitement.
Oups (modifié).
Je veux dire n'est-il pas un moyen de faire cela sans les génériques? Comme je l'ai dit je veux que les classes de base pour être utilisable en tant que-est - l'ajout de médicaments génériques permettrait de les rendre plus difficiles à utiliser, et supprime l'encapsulation de la BaseNode classe qui est censé être encapsulé par la Base.
OriginalL'auteur Cam | 2010-04-03
Vous devez vous connecter pour publier un commentaire.
Vous devez utiliser le instanceof mot-clé pour vérifier le type de l'objet référencé par n et transtypage de l'objet et l'appel de la bar() méthode. La Caisse Dérivés.bar() méthode soufflet
OriginalL'auteur Babar
parce que si B extends C, cela signifie que B est un C et non C est une B.
repenser à ce que vous essayez de faire.
OriginalL'auteur Omry Yadan
Les questions /réponses sont bien en termes d'un résumé de l'argument, mais je voudrais faire un plus concrète. Supposons que vous pourrait le faire. Ce code aurait pour compiler et exécuter:
Exactement où serait la mise en œuvre de la
read
méthode venir? Il est résumé dansInputStream
. Où serait-il d'obtenir les données à partir de? Il a simplement n'est pas appropriée pour traiter un nu -java.lang.Object
comme unInputStream
. C'est beaucoup mieux pour le casting de lever une exception.Dans mon expérience, il est difficile d'obtenir un "parallèle les hiérarchies de classe", comme celle que vous décrivez au travail. Vous peut trouver que les génériques d'aide, mais il peut s'arracher les cheveux très rapidement.
OriginalL'auteur Jon Skeet
Vous pouvez créer un constructeur de B, qui prend C comme un paramètre.
Voir ce post pour les idées, de faire ce que vous essayez de faire.
OriginalL'auteur Joel
Vous ne pouvez pas le faire parce que C n'est pas nécessairement de mettre en œuvre les comportements que vous avez créé lors de l'extension dans B.
Donc, dire que C est une méthode
foo()
. Alors vous savez que vous pouvez appelerfoo()
sur un B, B extends C, de sorte que vous pouvez convertir en conséquence un régal un B comme si c'était un C avec(C)(new B())
.Cependant - si B est une méthode
bar()
, rien dans la sous-classe de la relation, dit que vous pouvez appelerbar()
sur C trop. Donc vous ne pouvez pas traiter un C comme si il s'agissait d'un B, et donc vous ne pouvez pas exprimés.OriginalL'auteur brabster
Dans votre exemple, vous pouvez lancer n dans un DerivedNode si vous êtes certain que ce n, est une instance de DerivedNode, ou vous pouvez utiliser des génériques:
OriginalL'auteur Maurice Perry
Classes de Base ne sais rien à propos de classes dérivées, sinon les problèmes mis en évidence ci-dessus vont se poser. Passer est un " code d'odeur, et de passer dans la classe de base d'une classe dérivée est particulièrement 'puant'. De tels motifs peuvent conduire à difficile à résoudre des dépendances circulaires.
Si vous voulez une classe de base pour faire usage de la classe dérivée implémentations utilisent la méthode de Modèle de modèle que j'ai.e ajouter une méthode virtuelle ou abstraite dans votre classe de base et de la remplacer et de mettre en œuvre dans la classe dérivée. Ensuite, vous pouvez en toute sécurité appelez cela à partir de la classe de base.
OriginalL'auteur rich s
Parce que si
B extends C
, alors B peut avoir des choses qui n'est pas dans C (comme les variables d'instance de l'initialisation dans le constructeur qui ne sont pas dans le new C())OriginalL'auteur glebm