2017-10-21 119 views
5

例如我有一个处理器基类与返回一个对象,并采取对象作为参数的方法。我想扩展它,并创建一个StringProcessor将返回字符串,并采取String作为参数。然而 协打字只能用返回值,但不允许参数。这种限制的原因是什么?在Java方法重载为什么允许有协变返回类型,但不是协变的参数?

class Processor { 
    Object process (Object input) { 
     //create a copy of input, modify it and return it 
     return copy; 
    } 
} 

class StringProcessor extends Processor { 
    @Override 
    String process (String input) { // permitted for parameter. why? 
     //create a copy of input string, modify it and return it 
     return copy; 
    } 
} 

回答

10

The Liskov principle。在设计处理器类,你写一份合同说:“一个处理器能够使用任何对象作为参数,并返回一个对象”。

的StringProcessor是处理器。所以它应该遵守这个合同。但是,如果它仅接受String作为参数,则违反了该合同。请记住:处理器应该接受任何对象作为参数。

所以,你应该能够做到:

StringProcessor sp = new StringProcessor(); 
Processor p = sp; // OK since a StringProcessor is a Processor 
p.process(new Integer(3456)); 

当返回一个字符串,它不违反合同:它应该返回一个对象,一个String是一个对象,所以一切都很好。

你可以做你想要达到的目标,通过使用泛型:

class Processor<T> { 
    Object process (T input) { 
     //create a copy of input, modify it and return it 
     return copy; 
    } 
} 

class StringProcessor extends Processor<String> { 
    @Override 
    String process (String input) { 
     return copy; 
    } 
} 
0

另外,如果你想有一个类型的理论回答,这样做的原因是,考虑到函数类型的子类型关系的情况下,关系是在返回类型协变,但在参数类型逆变(即X -> YU -> W亚型如果YW亚型和UX一个子类型)。

相关问题