2011-01-09 4 views
3

У меня есть абстрактный метод шаблона:Java перегруженный метод

class abstract MyTemplate 
{ 
    public void something(Object obj) 
    { 
     doSomething(obj) 

    } 

    protected void doSomething(Object obj); 

} 

class MyImpl extends MyTemplate 
{ 

    protected void doSomething(Object obj) 
    { 
     System.out.println("i am dealing with generic object"); 
    } 

    protected void doSomething(String str) 
    { 
     System.out.println("I am dealing with string"); 
    } 
} 


public static void main(String[] args) 
{ 
    MyImpl impl = new MyImpl(); 
    impl.something("abc"); // --> this return "i am dealing with generic object" 

} 

Как я могу напечатать «Я имею дело со строкой» без использования InstanceOf в DoSomething (объект Object)?

Thanks,

+1

С точки зрения ОО, я бы подумал, почему мне нужна такая конструкция. Экземпляры класса Object, не имеют большого количества поведения, зачем передавать их в качестве параметров? –

+0

То же, что сказал Хорст. Если вы собираетесь определить свой базовый класс для работы с типом «Объект» в его сигнатурах метода, вы действительно не должны предполагать обработку определенного типа. Вместо этого я бы предложил определить иерархию классов для MyTemplate с помощью генериков. – whaley

ответ

2

Ну, вы действительно не можете этого сделать. Java не может выполнять двойную отправку из коробки. Проблема в том, что привязка вызовов метода обычно выполняется в основном во время компиляции.

Здесь http://en.wikipedia.org/wiki/Double_dispatch

и здесь

http://www.javaperformancetuning.com/articles/ddispatch2.shtml

0

Его невозможно. doSomething (Object obj) в MyImpl - это метод, который переопределяет doSomething в MyTemplate.

Используйте экземпляр-оператор в doSomething (Object obj) в MyImpl. В любом случае, это лучший стиль.

+1

Я думаю, что использование экземпляра, в общем, намекает на возможные нарушения Принципа замещения Лискова (LSP). –

+0

В этом случае подкласс, по-видимому, «оптимизирован» для специального типа объектов, хотя он способен обрабатывать все. Эрго нам нужно какое-то различие, и это делается с помощью instanceof. А также мне не нравится этот принцип, потому что подклассификация чего-то и использование вместо исходного объекта - это ИМХО хороший способ изменить программу. Может быть, я просто не понял этого принципа. – Daniel

+0

Полиморфизм должен быть предпочтительным для примеров этих вещей.Кроме того, если вы проверяете (и потенциально бросаете) определенный подтип внутри метода, тогда ваш метод должен принять подтип как параметр, а не супертип (который может быть выполнен с помощью дженериков в примере, предоставленном OP). – whaley

0

Короче говоря, вы не можете. Другие ответы объяснили, почему. Альтернативой может быть использование дженериков вместо этого и полагаться на определенный подтип вашего абстрактного класса для обработки строк (или другого конкретного класса). Например:

abstract public class MyTemplate<T> { 
    abstract public void doSomething(T t); 
} 

public class MyTemplateImpl extends MyTemplate<Object> { 

    @Override 
    public void doSomething(Object o) { 
     System.out.println("Dealing with a generic Object"); 
    } 
} 

public class MyTemplateImplForStrings extends MyTemplate<String> { 
    @Override 
    public void doSomething(String s) { 
     System.out.println("dealing with a String"); 
    } 
} 

Это означает, что ваш код вызова будет выглядеть следующим образом:

MyTemplateImplForStrings template = new MyTemplateImplForStrings(); 
template.doSomething("hello"); //prints ""dealing with a String" 

или

MyTemplate<String> template = new MyTemplateImplForStrings(); 
template.doSomething("hello"); //prints ""dealing with a String" 

Примечание: вы хотите, чтобы избежать использования абстрактной основы в качестве справки type, если вы не параметризуете его также с помощью String; иначе вы оставите дверь открытой для ClassCastExceptions во время выполнения, о которой должен предупредить компилятор.

0

Компилятор java использует тип времени компиляции аргументов метода для создания вызова метода, который в вашем примере представляет собой Object, а не String. Тип выполнения аргументов игнорируется вызовами методов.

Вы можете либо попробовать visitor pattern, если вы контролируете все классы ввода, либо используете reflection, что является медленным/сложным и легко ошибиться.