2016-06-17 3 views
4

je une hiérarchie de classes qui ressemble un peu à ceci:méthode d'appel de type dynamique

class Parent { } 
class Child1 extends Parent {} 
class Child2 extends Parent {} 
class Child3 extends Parent {} 

Dans une autre classe, j'ai des méthodes qui ressemble à ceci:

void doSomething(Parent p) { //default } 
void doSomething(Child1 c) { //implementation for Child 1 } 
void doSomething(Child2 c) { //implementation for Child 2 } 

Actuellement, quand j'ai quelque chose comme ce

Parent p = new Child2(); 
doSomething(p); 

la première méthode, doSomething(Parent) est appelé au lieu de 0 doSomething(Child2) Supposons que j'ai une liste d'éléments avec le type statique de Parent et un type dynamique de ChildN. Comment puis-je assurer la méthode, à condition que le type dynamique soit appelé, sans lancer. Seulement pour Child3 (pas de méthode doSomething spécifique) Je veux appeler l'implémentation par défaut.

Répondre

3

Ce que vous recherchez est appelé « l'envoi multiple ou « l'envoi dynamique. » - et n'existe pas en Java

En Java, le compilateur décide de choisir la méthode en cas de surcharge (. et c'est ce qui arrive quand vous avez trois méthodes avec le même nom mais différents types de paramètres.) Cela arrive à la compilation, et si votre objet Parent "runtime" se trouve être un objet Child1, cela n'a pas d'importance. fixe la méthode à appeler - comme dit: java ne prend pas en charge la répartition dynamique

En ce sens, le correc La solution Java serait de mettre une méthode "doSomething()" sur votre classe Parent; et que chaque enfant annule la méthode pour la chose spécifique.

Dans le cas où "doSomething()" ne correspond pas vraiment à cette classe; vous pouvez jeter un oeil dans le visitor pattern. Une autre option serait d'utiliser instanceof ... mais vous devriez « cacher » correspondant si/chaîne d'autre ... en utilisant à nouveau polymorphisme, comme:

interface DoIt { void doSomething() } 
class ParentDoIt implements DoIt ... 
    same for Childs 

class DoItFactory { 
    DoIt getDoIt(Parent p) { 
    if (p instanceof Child1) return new Child1DoIt(p) 
    ... 
0

je le ferais comme ça.

interface SomeAction { void doSomething(); } 

class Parent implements SomeAction { //override doSomething here } 
class Child1 extends Parent {//override doSomething here } 
class Child2 extends Parent {//override doSomething here } 
class Child3 extends Parent { // no need to override here} 

maintenant

Dans une autre classe, j'ai méthodes Ressemblant cette

void doSomething(SomeAction p) { //default } 

Parent p = new Child2(); 
doSomething(p); 

p.doSomething(); // would call Child 2 
+0

Merci, je l'aurais fait, mais je impossible de modifier mes classes parent ou enfant – Karl

+0

@Karl Oui, vous devrez peut-être modifier la classe parent implémenter l'interface et l'autre classe.Si ce n'est pas possible alors vous devrez peut-être vérifier en utilisant instanceof qui dégraderait les performances. – Beniton

2

Une solution pourrait être que la méthode doSomething utilise la logique du paramètre:

class Parent { 
    public void neededMethod() {//default} 
} 

class Child1 { 
    public void neededMethod() {//implementation for Child 1} 
} 

Ensuite, dans votre code:

void doSomething(Parent p) { 
    //more code 
    p.neededMethod(); 
    // code 
} 

Si cette solution ne vous convient pas parce que vous avez besoin d'une sorte d'un répartiteur, alors vous devrez utiliser instanceof puis appeler la méthode appropriée:

void doSomething (Parent p) { 
    if (p instanceof Child1) doSomethingWithChild1(p); 
    else if (p instanceof Child2) doSomethingWithChild2(p); 
    ... 
    else defaultSomething(p); 
}