2011-09-07 67 views
5

java中的覆盖方法具有以下功能:java中的覆盖方法约束

1> Overrinding方法应该具有与Parent类方法相同的参数列表。

2>返回类型应该与父类方法的返回类型相同/子类。

3>访问级别应与父类方法相同或更少限制。

4>重写方法可以抛出相同或更窄的异常,而不是更广泛的。

* 只是想知道为什么会这样的点*

* 2 - 为什么子为什么不超? *

3 - 为什么访问级别应该限制较少?

4 - 为什么它应该抛出狭窄的异常?

按我的理解它只是如果我创建一个父类refrence创建一个子类对象,并试图跑下来每个场景,然后

让我们假设A是父类B是子类均具有方法printAndReturnSomething()

public class A{ 

     public B printAndReturnSomething(){ 
       S.O.P("Inside A Print"); 
       return new B(); 
       } 
} 

现在我们有孩子的B类为

public class B extends A{ 
     public A printAndReturnSomething(){ // I know this isn't possible to return A but had it been then 
       S.O.P("Inside A Print"); 
       return new A(); 
       } 
} 

现在,如果我做这样的事情

A a =new B(); 

,现在我有一个这样的引用我期待的返回类型为B型的

B returnedValue=a.printAndReturnSomething(); // But it actually calls the child class method and hence returns A. So here comes the contradiction. 

Similaraly为情景3和4.我的理解是否正确?我错过了其他更相关的东西吗?

回答

5

所有这一切都可以归纳为“一个子类必须表现得好像它是一个超类”。因此,如果Derived延伸了Base并且我有Derived类型的对象x,那么我希望它的行为与Base类型完全相同。

所以如果x.foo()返回某种类型的T,并且Base::foo()返回类型S,那么我希望能够治疗x.foo()S,所以T最好是相同或S一个子类。

同样,x.foo()应该只会抛出Base:foo()承诺的例外情况。它无法开始抛出新的意外的例外。

如果Base::foo()是公开的,那么x.foo()应该如此。你不能突然对派生类有更严格的限制,因为基类向我保证它是公开的。

总是将继承看作“行为像超类”,或者“可以像超类一样对待”,所有这些都应该清楚。

+0

感谢您的回答,特别是最后一行“始终将继承看作”像超类一样行事“,或者”可以像超类一样对待“,所有这些都应该清楚。 – Deva

3

点#2

想象以下:

class Animal {} 
class Dog extends Animal {} 

class Base { 
    Dog get() { ... } 
} 

class Derived extends Base { 
    Animal get() { ... } 
} 

Base b = new Derived(); 
Dog d = b.get(); // What? 

类似的逻辑可被施加到其他的问题。

+0

感谢您的回复。这个问题我已经提到过了。我想检查的是这是唯一的原因? – Deva

+2

@Deva:这是一个非常重要的原因!它根本没有任何意义。 –

+0

Yup Thanks Oli .. – Deva

1

要回答你两点:

2 - 为什么子为什么不超?

若父类被允许,这可能发生:

class A { 
    public A makeCopy() { return clone(); } 
} 

class B extends A { 
    public Object makeCopy() { return new Date(); } 
} 

public static void main(String[] args) { 
    A a = new B(); 
    A copy = a.makeCopy(); // OOPS -- didn't get an A after all! 
} 

3 - 为什么访问级别应该是限制较少?

修改上面的B类:

class B extends A { 
    private A makeCopy() { return clone(); } 
} 

public static void main(String[] args) { 
    A a = new B(); 
    A copy = a.makeCopy(); // OOPS -- accessing a private method! 
} 

4 - 为什么要抛出异常狭窄?

同样的想法 - 如果A.makeCopy宣布抛出AException(假设的例外A声明的类),但B.makeCopy被宣布扔Throwable,然后B.makeCopy可以扔任何东西。这将使得在main中不可能合理地编写try/catch块。

4

按我的理解它只是如果我创建一个父类refrence创建一个子类对象,并试图跑下来每个场景......

我想你groked正确的想法。

案例与父类引用子类对象是哪里所谓Liskov substitution principle发挥作用:在计算机程序中,如果S是T的子类型,那么类型T的对象[这是你的“父类”] 可以用类型S [也就是你的“子类对象”] (即,类型S的对象可以替代类型T的对象)的对象替换,而不改变该程序的任何期望属性(正确性,任务演出等)...

+1

+1提里斯科夫替代原则 – Andrey