Consider the following two classes:
public class Sup3r {
public void sup3rMethod() {}
}
public class Child extends Sup3r {
public void childMethod() {}
}
and the following three statements:
s.sup3rMethod();
c.childMethod();
s.childMethod();
The last statement gives
Cannot resolve method 'childMethod' in 'Sup3r'
Why?
because the method childMethod only exists in the subclass Child. Sup3r is not inheriting this method from Child therefore the childMethod cannot be called using s.
If the reference variable s contains a Child instance then you can make it work by casting s to a
Child type first and then calling the method on s.
((Child)s).childMethod();
If the reference variable s does not in fact contain a Child instance then you will get a ClassCastException instead.
EDIT:
There is one other way you could make it work and that is by making the superclass Sup3r abstract and adding the abstract method childMethod()
to the class like so:
public abstract class Sup3r {
public void sup3rMethod() {}
public abstract void childMethod();
}
public class Child extends Sup3r {
public void childMethod() {} //implementation code here, the empty block would suffice too however.
}
abstract means that you leave the implementation of the method childMethod() to one of Sup3rs implementing subclasses. If you make this change to your code then you should be able to call childMethod() on s without having to cast to Child first. But the result of childMethod() will depend on the specific childMethod() method implementation of the subclass instance that s references.
Related
abstract class Base{
protected abstract void a();
}
class Child extends Base{
#Override
public void a(){
//why is this valid
}
}
Why is that we can't reduce the visibility but can increase it?
Also I need to implement Template pattern in which the public methods visible can only be of base class.
Example:
abstract class Base{
public void callA(){
//do some important stuff
a();
}
protected abstract void a();
}
class Child extends Base{
#Override
public void a(){
//why is this valid
}
}
Now if java allows to increase visibility then there are two methods visible publicly??
I know interface is one solution but is there some other way out???
Why decreasing visibility is not allowed is already explained in other responses (it would break the contract of the parent class).
But why it is allowed to increase the visibility of a method? First, it would not break any contract, so there is no reason to not allow it. It can be handy sometimes, when it makes sense in the child class for a method to not be protected.
Second, not allowing it could have the side effect of making impossible sometimes to extend a class and implement an interface at the same time:
interface Interface1 {
public void method();
}
public class Parent {
protected abstract void method();
}
public class Child extends Parent implements Interface1 {
#Override
public void method() {
}
//This would be impossible if the visibility of method() in class Parent could not be increased.
}
About your second question, you can do nothing about it. You have to trust that the person who implements the child class doesn't do anything that breaks your implementation. Even if java wouldn't allow to increase visibility, that would still not fix your problem, because a public method with a different name could be created that calls the abstract method:
class Child extends Base{
#Override
protected void a(){
}
public void a2() {
a(); //This would have the same problems that allowing to increase the visibility.
}
}
If the base class makes a promise regarding visibility, then the subclass cannot break that promise and still satisfy the Liskov substitution principle. You can't use a subclass in any situation where the promised method is exposed if that promise is broken.
The subclass IS-A base class. If the base class exposes a method, so must the subclass.
There's no way out in Java or C++. I'd guess the same is true in C#.
Why is that we can't reduce the visibility but can increase it?
Suppose that it would be possible to reduce the visibility. Then look at the following code:
class Super {
public void method() {
// ...
}
}
class Sub extends Super {
#Override
protected void method() {
// ...
}
}
Suppose that you would have another class, in another package, where you use these classes:
Super a = new Sub();
// Should this be allowed or not?
a.method();
To check whether a method call is allowed or not, the compiler looks at the type of the variable you call it on. The type of the variable a is Super. But the actual object that a refers to is a Sub, and there the method is protected, so you would say it should not be allowed to call the method from an unrelated class outside the package. To solve this strange situation, it's made forbidden to make overridden methods less visible.
Note that the other way around (making a method more visible) doesn't lead to the same problem.
Since Java allows Super class reference to point to sub class object.. So, restriction should not be increased from compile-time to runtime..
Lets see this through an example: -
public class B {
public void meth() {
}
}
class A extends B {
private void meth() { // Decrease visibility.
}
}
Now, you create an object of class A and assign it the reference of class B..
Lets see how: -
B obj = new A(); // Perfectly valid.
obj.meth(); // Compiler only checks the reference class..
// Since meth() method is public in class B, Compiler allows this..
// But at runtime JVM - Crashes..
Now, since compiler only checks the type of the reference variable, and check the visibility of methods in that class (class B), and it doesn't check what kind of object does the reference obj refers to.. So, it is not worried about that.. It is left to JVM at runtime to resolve the appropriate method..
But at runtime, JVM will actually try to invoke the meth method of class A as object is of class A.. But, now what happens... BooooOOMM ---> JVM Crashes.. because meth method is private in class A...
That's why visibility is not allowed to be decreased..
Consider the code below :
abstract class AbstractClass {
abstract m1();
}
public class Test {
public static void main(String [] args) {
AbstractClass obj = new AbstractClass() {
#Override void m1() {
System.out.print("Instance of abstract class !");
}
};
obj.m1();
}
}
Now here is what I did not understand about this code.
I read that anonymous class creates the class with unknown name which extends the class whose reference is provided (here it is abstract AbstractClass).
Also I remember that we cannot implement the method of child class if the the object is having reference of parent class.
see block of code below
Parent obj = new Child();
obj.methodOfParent();
obj.methodOfChild(); //this gives error
Now here is my point if Anonymous Class extends its Parent Class whose reference is provided, then how can we call overriden methods of Parent Class from Anonymous Class?
I guess you just miss one point. Let me show you example:
class Parent {
public void methodOfParent() {}
public void methodOfParentToBeOverriden() {}
}
class Child extends Parent {
#Override public void methodOfParentToBeOverriden() {}
public void methodOfChild() {}
}
Parent obj = new Child();
obj.methodOfParent(); //this is OK
obj.methodOfParentToBeOverriden(); // this is OK too
obj.methodOfChild(); //this gives error
((Child)obj).methodOfChild(); //this is OK too here.
Please note that when you call obj.methodOfParentToBeOverriden() it will be called implementation from Child class. Independence did you cast this object to Parent type or not.
There is a difference between calling an overridden method of parent and calling a method of child. If a method is declared in class T, you can call it on a variable statically typed as T, regardless of where the method is actually implemented.
In your example, if obj.methodOfParent() happens to be a method override from Child, the method in Child will run, even though obj's static type is Parent.
Same mechanism is in play with anonymous classes: the reason that you are allowed to call obj.m1() is that m1() has been declared in the parent class.
There something ambiguous about this idea and I need some clarifications.
My problem is when using this code:
public class B {
private void don() {
System.out.println("hoho private");
}
public static void main(String[] args) {
B t = new A();
t.don();
}
}
class A extends B {
public void don() {
System.out.println("hoho public");
}
}
The output is hoho private.
Is this because the main function is in the same class as the method don, or because of overriding?
I have read this idea in a book, and when I put the main function in another class I get a compiler error.
You cannot override a private method. It isn't visible if you cast A to B. You can override a protected method, but that isn't what you're doing here (and yes, here if you move your main to A then you would get the other method. I would recommend the #Override annotation when you intend to override,
class A extends B {
#Override
public void don() { // <-- will not compile if don is private in B.
System.out.println("hoho public");
}
}
In this case why didn't compiler provide an error for using t.don() which is private?
The Java Tutorials: Predefined Annotation Types says (in part)
While it is not required to use this annotation when overriding a method, it helps to prevent errors. If a method marked with #Override fails to correctly override a method in one of its superclasses, the compiler generates an error.
is this because the main function is in the same class as the method "don"
No, it's because A's don() is unrelated to B's don() method, in spite of having the same name and argument list. private methods are hidden inside their class. They cannot be invoked directly by outside callers, such as main method in your case, because they are encapsulated inside the class. They do not participate in method overrides.
No, a private method cannot be overridden since it is not visible from any other class. You have declared a new method for your subclass that has no relation to the superclass method. One way to look at it is to ask yourself whether it would be legal to write super.func() in the Derived class.
You can't override a private method, but you can introduce one in a derived class without a problem. The derive class can not access the private method on the ancestor.
Since t is a on object of type B, calling don() method will invoque the method defined at B. It doesn't even know that there is a method named also don() at class A
private members aren't visible to any other classes, even children
You can't override a private method, but then again, you can't call it either. You can create an identical method with the same name in the child however.
public class A
{
private int calculate() {return 1;}
public void visibleMethod()
{
System.out.println(calculate());
};
}
public class B extends A
{
private int calculate() {return 2;}
public void visibleMethod()
{
System.out.println(calculate());
};
}
If you call A.visibleMethod() it prints out 1.
If you call B.visibleMethod() it prints 2.
If you don't implement the private calculate() method in B, it won't compile because the public method that calls it can't see the private method in A.
Let's say I have a method called mymethod()
and this method overrides the method of the super class method.
What does it mean to override a method?
Does that mean mymethod() ignores everything that is in the method of the superclass, or does that means mymethod() also includes everything in the superclass method?
When overriding a method, can I only override the methods of the same name, or I can override methods of any name?
thanks.
An example:
public class Base {
public void saySomething() {
System.out.println("Hi, I'm a base class");
}
}
public class Child extends Base {
#Override
public void saySomething() {
System.out.println("Hi, I'm a child class");
}
}
Now assume we have a main function somewhere...
public static void main(String [] args) {
Base obj = new Child();
obj.saySomething();
}
When this runs, it will call Child's version of saySomething, because you overrode the parent's version by giving a new version of the function in Child.
The #Override annotation allows other developers (and you, when you forget) to know that this method overrides something in a base class/interface, and it also allows the compiler to yell at you if you're not actually overriding anything in a base class. For example, if you got the number of arguments wrong for a function, the compiler will give you an error saying your #Override is incorrect.
For example:
public class Child extends Base {
#Override
public void saySomething(int x) {
System.out.println("I'm a child and x is: " + x);
}
}
The compiler will yell at you because this version of saySomething takes an argument, but the parent's version doesn't have an argument, so you're #Override-ing something that's not in the parent.
On super
The Child version of saySomething will not invoke the Base version, you have to do it yourself with super.method().
For example:
public class Child extends Base {
#Override
public void saySomething() {
super.saySomething();
System.out.println("I'm also a child");
}
}
If you ran the main and used this Child class, it would print out I'm a base and I'm also a child.
Overriding means that when you call a method on your object, your object's method is called instead of the super class. The #Override annotation is something you use to make sure that you are overriding the correct method of the superclass. If you annotate a method that does not exist in the superclass, the Java compiler will give you an error. This way you can be sure that you are overriding the correct methods. This is especially useful in cases like this:
public class MyClass {
...
public boolean equals(MyClass myClass) {
...
}
}
There is a logic-bug in the code above. You haven't actually overridden the Object class's equals method. If you add the #Override annotation:
public class MyClass {
...
#Override
public boolean equals(MyClass myClass) {
...
}
}
The Java compiler will now complain because there is no corresponding method in the parent class. You'll then know that the correct solution is:
public class MyClass {
...
#Override
public boolean equals(Object o) {
...
}
}
To call the parent class's method, you can call super.overriddenMethod() where overriddenMethod is the name of the method you have overridden. So if you want to do something in addition to what the parent class already does, you can do something like this:
public class MyClass {
...
#Override
public void overriddenMethod() {
super.overriddenMethod();
/* whatever additional stuff you want to do */
}
}
If an inheriting class has on override method of the same name as the parent class it will be called instead of the one in the parent class. This only works if the names are the same, and of course if the signature of the method matches your call to the method.
What does it mean to override a method?
It means you replace the super class definition of the method with your own definition.
does that mean mymethod() ignores everything that is in the method of the super class?
or does that means mymethod() also includes everything in the superclass method?
You can choose whether to include the super class definition within your definition. To include it, you need to call super.mymethod() within mymethod().
and when overriding a method, can I only override the methods of the same name, or I can override methods of any name?
To override a method, you must supply a method in the sub class with the same signature (which means the same name, parameters and return type).
As a side note, the #Override annotation in your question does not actually cause your method to override another method. It causes a compile-time error if a method annotated with it does not have a signature matching a public or protected method of a super class (or interface as of 1.6).
I once had a student come to ask me why his code wasn't working. He had spent several days wondering why he could put something into a collection but was not able to find it. His code was something like:
public int hashcode()
instead of:
public int hashCode()
So the hashCode method never got called.
Adding #Overrides to a method makes it clear that you are overriding the method AND make sure that you really are overriding a method.
When you override a method of the super class, calling that method on your object calls its method instead of that of the super class.
You can call the super class's method (despite having overridden it) using super.methodName(). A common reason for this is when the overridden method would otherwise reimplement the super class method and add additional code specific to the extending class (public void methodName() { super.methodName(); /* more code */ }).
#Override annotation allows you to cause warning at compile time if the method isn't actually overriding anything. It isn't necessary, but these warning are a hit to you that you might have got the signature wrong in the extending class, forgot to implement the method at all in the super class, or some other silly mistake.
I have a parent class which has a method, in the child class I override that parent class's method. In a third class I make an object of child and by using that object I want call the method of parent class. Is it possible to call that parent class method ? If yes, then how?
If you override a parent method in its child, child objects will always use the overridden version. But; you can use the keyword super to call the parent method, inside the body of the child method.
public class PolyTest{
public static void main(String args[]){
new Child().foo();
}
}
class Parent{
public void foo(){
System.out.println("I'm the parent.");
}
}
class Child extends Parent{
#Override
public void foo(){
//super.foo();
System.out.println("I'm the child.");
}
}
This would print:
I'm the child.
Uncomment the commented line and it would print:
I'm the parent.
I'm the child.
You should look for the concept of Polymorphism.
Use the keyword super within the overridden method in the child class to use the parent class method. You can only use the keyword within the overridden method though. The example below will help.
public class Parent {
public int add(int m, int n){
return m+n;
}
}
public class Child extends Parent{
public int add(int m,int n,int o){
return super.add(super.add(m, n),0);
}
}
public class SimpleInheritanceTest {
public static void main(String[] a){
Child child = new Child();
child.add(10, 11);
}
}
The add method in the Child class calls super.add to reuse the addition logic.
First of all, it is a bad design, if you need something like that, it is good idea to refactor, e.g. by renaming the method.
Java allows calling of overriden method using the "super" keyword, but only one level up in the hierarchy, I am not sure, maybe Scala and some other JVM languages support it for any level.
Say the hierarchy is C->B->A with A being the base class.
I think there's more to fixing this than renaming a method. That will work but is that a fix?
One way is to refactor all the functionality common to B and C into D, and let B and C inherit from D: (B,C)->D->A Now the method in B that was hiding A's implementation from C is specific to B and stays there. This allows C to invoke the method in A without any hokery.
NOTE calling parent method via super will only work on parent class,
If your parent is interface, and wants to call the default methods then need to add interfaceName before super like IfscName.super.method();
interface Vehicle {
//Non abstract method
public default void printVehicleTypeName() { //default keyword can be used only in interface.
System.out.println("Vehicle");
}
}
class FordFigo extends FordImpl implements Vehicle, Ford {
#Override
public void printVehicleTypeName() {
System.out.println("Figo");
Vehicle.super.printVehicleTypeName();
}
}
Interface name is needed because same default methods can be available in multiple interface name that this class extends. So explicit call to a method is required.