Overriding Methods constraints in java
Overriding Methods in java have the following features :
1> The Overrinding method should have the same argument list as the Parent class method.
2> The return type should be the same/subclass of the return type for the parent class method.
3> The access level should be same or less restrictive as the parent class method.
4> The overriden method can throw the same or Narrower exception and not a broader one.
*Just wanted to know why is it so for point *
*2 - why subclass why not a superclass?*
3 - why the access level should be less restrictive?
4 - why it should throw narrow exception?
As per my understanding its just that if i am creating a parent class refrence to create a child class object and trying to run down each of the scenario then
Lets assume A is parent class and B is child class both having method printAndReturnSomething()
public class A{
public B printAndReturnSomething(){
S.O.P("Inside A Print");
return new B();
}
}
Now we have the child class B as
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();
}
}
Now if i do something like this
A a =new B();
and now as i have a reference of A so i expect the return type to be of type B
B returnedValue=a.printAndReturnSomething(); // But it actually calls the child class method and hence returns A. So here comes the contradiction.
Similaraly for the scenarios 3 and 4. Is my understanding correct? A开发者_如何转开发m i missing something else more relevant?
All of this can be summarized by saying that "a subclass has to behave as if it was a superclass". So if Derived
extends Base
and I have an object x
of type Derived
, then I want it to behave exactly as if it were of type Base
.
So if x.foo()
returns some type T
, and Base::foo()
returns a type S
, then I want to be able to treat x.foo()
as an S
, so T
better be the same as or a subclass of S
.
Similarly, x.foo()
should only throw exceptions that Base:foo()
promises. It can't start throwing new, unexpected exceptions.
If Base::foo()
is public, then so should x.foo()
be. You can't suddenly have a tighter restriction on the derived class, because the base class promised me that it was public.
Always think of inheritance as "behaves like the super class", or "can be treated like the superclass", and all this should be clear.
As per my understanding its just that if i am creating a parent class refrence to create a child class object and trying to run down each of the scenario...
I think you groked the idea correctly.
Case with parent class referencing subclass object is where so called Liskov substitution principle comes into play: in a computer program if S is a subtype of T, then objects of type T [that's your "parent class"] may be replaced with objects of type S [that's your "child class object"] (i.e., objects of type S may be substitutes for objects of type T), without altering any of the desirable properties of that program (correctness, task performed, etc.)...
Point #2
Imagine the following:
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?
Similar logic can be applied to the other questions.
To answer your points:
2 - why subclass why not a superclass?
If a superclass were allowed, this could happen:
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 - why the access level should be less restrictive?
Modify the above B class to:
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 - why it should throw narrow exception?
Same idea -- if A.makeCopy
was declared to throw an AException
(a hypothetical exception class declared in A
), but B.makeCopy
was declared to throw Throwable
, then B.makeCopy
could throw just about anything. That would make it impossible to rationally code a try/catch block in main
.
精彩评论