java中的重写方法具有以下功能:
1> Overrinding方法应该与Parent类方法具有相同的参数列表。
2 - ;返回类型应该是父类方法的返回类型的相同/子类。
3>访问级别应与父类方法相同或更少限制。
4> overriden方法可以抛出相同或更窄的异常而不是更广泛的异常。
* 只是想知道为什么点*
* 2 - 为什么不是超类的子类? *
3 - 为什么访问级别限制较少?
4 - 为什么它应该抛出狭隘的异常?
根据我的理解,只是如果我正在创建一个父类引用来创建子类对象并尝试运行每个场景,那么
让我们假设 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();
现在因为我有A的引用所以我希望返回类型是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.我的理解是否正确?我错过了其他更相关的东西吗?
答案 0 :(得分:5)
所有这些都可以通过说“子类必须表现得好像它是一个超类”来概括。因此,如果Derived
扩展Base
并且我有x
类型的对象Derived
,那么我希望它的行为与Base
类型完全相同。
因此,如果x.foo()
返回某种类型T
,而Base::foo()
返回类型S
,那么我希望能够将x.foo()
视为{ {1}},因此S
最好与T
或[{1}}的子类相同。
同样,S
只应抛出x.foo()
承诺的异常。它无法开始抛出新的意外异常。
如果Base:foo()
是公开的,那么Base::foo()
应该是公开的。你不能突然对派生类有更严格的限制,因为基类承诺我是公开的。
始终将继承视为“表现得像超类”,或“可以像超类一样对待”,所有这一切都应该清楚。
答案 1 :(得分:4)
根据我的理解,只是如果我创建一个父类引用来创建子类对象并尝试运行每个场景...
我认为你正确地理解了这个想法。
父类引用子类对象的情况是所谓的Liskov substitution principle发挥作用的地方:如果S是T的子类型,则计算机程序中的,然后是T类型的对象 [这是你的“父类”] 可以用S类型的对象替换 [这是你的“子类对象”] (即,类型S的对象可以替代T)类型的对象,不改变该程序的任何理想属性(正确性,执行任务等)......
答案 2 :(得分: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?
类似的逻辑可以应用于其他问题。
答案 3 :(得分: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块。