2016-06-17 3 views
4

У меня есть иерархия классов, который выглядит примерно так:метод вызова динамического типа

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

В другом классе я методы глядя, как это:

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

В настоящее время, когда у меня есть что-то вроде этот

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

первый метод, doSomething(Parent) вызывается вместо doSomething(Child2)

Предположим, у меня есть список элементов со статическим типом родителя и динамическим типом ChildN. Как я могу заверить, что метод, предоставляемый для динамического типа, называется без кастинга. Только для Child3 (никакого специального метода doSomething) Я хочу вызвать реализацию по умолчанию.

ответ

3

То, что вы ищете, называется «мульти отправки или„динамической отправки“. - и не существует в Java

В Java, компилятор решает, какой способ выбрать в случае перегрузки (. и это то, что происходит, когда у вас есть три метода с тем же именем, но с разными типами параметров). Это происходит во время компиляции, и если ваш объект «Родительский» родительский объект является объектом Child1, это не имеет значения. исправлено метод вызова - как сказано: java не поддерживает динамическую отправку.

В этом смысле коррекция t Java-решение должно было бы поместить метод «doSomething()» в ваш родительский класс; и иметь каждого ребенка переопределить этот способ к конкретной вещи.

В случае, если «doSomething()» на самом деле «не подходит» в этот класс; вы можете взглянуть на visitor pattern. Другим вариантом было бы использовать InstanceOf ... но тогда вы должны «скрыть» соответствующий, если/иначе цепь ... снова используя полиморфизм, как:

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

Я хотел бы сделать это, как это.

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} 

Теперь

В другом классе у меня есть методы, глядя, как этот

void doSomething(SomeAction p) { //default } 

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

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

Спасибо, я бы сделал это, но я не может редактировать мои родительские или дочерние классы – Karl

+0

@Karl Да, здесь вам, возможно, придется изменить класс родителя, реализующий интерфейс и другой класс.Если это невозможно, тогда вам, возможно, придется проверить с помощью instanceof, что ухудшит производительность. – Beniton

2

Решение может быть, что метод йоЗотеЬЫпд использует логику от параметра:

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

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

Тогда в вашем коде:

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

Если это решение не подходит вам, потому что вам нужно какое-то диспетчер, то вам придется использовать instanceof, а затем вызвать соответствующий метод:

void doSomething (Parent p) { 
    if (p instanceof Child1) doSomethingWithChild1(p); 
    else if (p instanceof Child2) doSomethingWithChild2(p); 
    ... 
    else defaultSomething(p); 
} 
Смежные вопросы