2011-01-09 70 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" 

} 

如何打印 “我处理字符串” W/O在DoSomething的(obj对象)使用的instanceof?

谢谢,

+1

从OO的角度来看,我会觉得很难,为什么我需要这样的构造。 Object类的实例没有太多的行为,为什么将它们作为参数传递? –

+0

同上Horst说什么。如果您要定义您的基类以在其方法签名中使用类型“对象”,那么您确实不应该假定处理特定的类型。我建议用泛型来定义MyTemplate的类层次结构。 – whaley

回答

0

它是不可能的。 MyImpl中的doSomething(Object obj)是重写MyTemplate中的doSomething的方法。

在MyImpl的doSomething(Object obj)中使用instanceof-operator。无论如何,这是更好的风格。

+1

我认为一般情况下,instanceof的用法暗示可能会违反Liskov替换原则(LSP)。 –

+0

在这种情况下,子类似乎对特殊类型的对象“优化”,尽管它能够处理所有对象。我们需要一些区别,这是由instanceof完成的。而且我也不喜欢这个原则,因为继承一些东西而不是原始对象是恕我直言的一种改变程序的好方法。也许我只是不明白这个原则。 – Daniel

+0

对于这些类型的事物,多态性应该优于instanceof。此外,如果您正在检查(并潜在地转换为)方法中的特定子类型,那么您的方法应该已接受子类型作为参数,而不是超类型(可以通过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" 

注意:你要避免使用抽象基作为您的参考键入,除非用String参数化它;否则,您将在运行时为ClassCastExceptions打开大门,编译器应该提醒您。

0

java编译器使用方法参数的编译时类型来创建方法调用,在您的示例中它是Object而不是String。方法调用会忽略参数的运行时类型。

如果您控制所有输入类或使用reflection,您可以尝试visitor pattern,这是缓慢/复杂且容易出错的。