We can not override a private method then why does the followng code does not give an error. Instead it produces the output.
class A {
private void fun() {
System.out.println("ths is a private method");
}
}
class B extends A {
void fun() {
System.out.println("ths is wrng");
}
}
class C {
public static void main(String args[]) {
B ob = new B();
ob.fun();
}
}
private methods are not inherited. In your main method you're invoking the fun() method on a variable of type B. The fun() method of type B seems to be accessible, assuming your class B and class C are in the same package.
Had you done this
A ob = new B();
ob.fun();
Then you would have gotten your compilation error.
B#fun() is completely unrelated to A#fun().
Both are completely different methods and not related to each other. As private methods are not inherited there is no concept of overriding here.
Method fun() is not overridden in B class because it was never inherited from class A.
What you are invoking in your code is method of B class and that has no relation with class A and method A#fun().
To check this, Add a #Override annotation and you will get compile time error.
// Compilation error.
Class B extends A{
#Override
void fun(){
System.out.println("ths is wrng");
}
}
Now this code will not compile.
First of all, private methods are not inherited in child classes. If you still try to write a method with same name as that of parent class, java compiler will consider the method in child class as a completely new method and will not throw any exception. Its like the new method in child class shadows the private method in parent class.
Related
Given two classes, a parent class and a child class:
class A {
private void greet() {
System.out.println("Class A");
}
}
class B extends A {
public void greet() {
System.out.println("Class B");
}
}
One has a method called greet(), which is private, and the other one defines a method with the same name, only that it is public. Now, as far as I know, the child's greet() method doesn't override the parent's method, because it 'hides' it? (given the fact that private methods can't be overridden?)
Now, given the following class and method (considered to be in the same package as A and B):
public class Main {
public static void main(String[] args) {
B b = new B();
b.greet();
}
}
This should compile. But this one:
public class Main {
public static void main(String[] args) {
A a = new B();
b.greet();
}
}
This one up here doesn't compile, because it's missing a typecast.
My question would be: why? If the greet() method was public in both places, it would have shown Class B both times. I'm pretty confused about why Java doesn't figure at runtime, for the second case, that a is actually referencing to an object of type B, and directly calls the method from class B.
Tried reading more about polymorphism in an OCA-preparation book, but the authors didn't seem to be so specific about it.
In your snippet that doesn't compile, the compiler sees that the compile time type of a is class A.
Therefore, it will only allow you to call accessible methods of class A (or of super-classes of A). greet is a private method of A, and therefore not accessible. Therefore the compiler doesn't allow calling it.
The fact that the runtime type of a would be class B, which has an accessible greet method, makes no difference, since the compiler doesn't try to figure out what the runtime type of a variable would be.
At compile time A.greet() is not accessible.
Hence does not compile.
For overriding, the method must be accessible at compile time, but the decision to call the method is done at runtime.
I was asked this question in a recent interview. Looking to get some help.
Class A has foo() method triggered from constructor.
public class A {
public A() {
foo();
}
public void foo() {
System.out.println("In foo method in class A");
}
}
Class B overrides the foo method in class A.
public class B extends A {
#Override
public void foo() {
System.out.println("In foo method in class B");
}
}
Now if we create instance of class B the foo() method in B will be called.
A a = new B();
prints: "In foo method in class B"
Question: Lets say we own the class A and it is part of a jar file(abc.jar) and how do we make sure when class B is instantiated A.foo() is called instead of overridden B.foo()?
Conditions:
Imagine the jar is shared to other users and we cannot break client code my marking the method private/final.
Also calling super.foo() from class B is also not an option since we don't own class B and cannot restrict users.
public class A {
public A() {
fooInternal();
}
public void foo() {
fooInternal();
}
private final void fooInternal() {
System.out.println("In foo method in class A");
}
}
You can't make it invoke A.foo(), because that method is overridden. You can only make it invoke a method that A.foo() invokes, and that can't be overridden.
The more important point here is that you shouldn't ever invoke overrideable methods from a constructor.
Mark A's foo method as final. It is the only way.
In order to still allow B to also get a ping on initialization, the solution is a two-stage construct: A's constructor invokes the final foo() method, but as part of the foo() method, foo2, or subfoo, or whatever you want to call it, is also invoked, and that method is defined in A as a noop (does nothing).
Generally such a final init()-style method should also be private. Based on common logic: What are the odds that an 'init' operation is also a concept that external code could plausibly want to invoke a second time at some arbitrary later point in time? Highly unlikely, which is why it should be private. Once you do so, well, private methods are effectively inherently final, so that takes care of that:
class A {
public A() {
init0();
}
private final init0() {
// do stuff here - subclasses won't stop you.
init();
}
// B can override this if it wants.
protected void init() {}
}
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.
public class B extends A{
public static void main(String[] args) {
new B().privateMethod();//no error -output B-privateMethod.Sounds like overriding
new B().staticMethod(); //no error -output B-StaticMethod.Sounds like overriding
}
private void privateMethod() {
System.out.println("B-privateMethod.");
}
static void staticMethod() {
System.out.println("B-StaticMethod.");
}
}
class A{
private void privateMethod() {
System.out.println("A-privateMethod.");
}
static void staticMethod() {
System.out.println("A-StaticMethod.");
}
}
On R&D I found in case of privateMethod()- since this method was not available on object of child class so child class's and parent class's privateMethod() are separate method and they have no relationship so this is not overriding.
but in case of staticMethod()- parent class's method was available on object of child class ,and when we define this in child class, object of child class start pointing to child class method.this looks like method overriding but not,since static method does not override.
how does static method handle by java developement kit?
new B().privateMethod();
this is not overriding, since B doesn't see A's privateMethod().
new B().staticMethod();
this is not overriding, calling a static method via an instance is allowed, though it can be confusing. It is exactly the same as calling it via the class name - B.staticMethod(). If a super class A of B has a static method visible from B, you can call that method from B (and it doesn't matter if you write B.staticMethod() or A.staticMethod() or new B().staticMethod().
If later you define a static method of the same name in B, that method hides the method of the same name in A, so calling B.staticMethod() or new B().staticMethod() now invokes B's static method. However, calling A.staticMethod() will still invoke A's static method.
Polymorphism is not for static methods. Static methods are called with JVM instructions invokestatic, whereas polymorphism is achieved with invokevirtual. The calls to static methods are determined at compile time, and polymorphic methods are dynamically dispatched at runtime.
You can easily tweak your code so that A.staticMethod() is called, by just assigning new B() to a variable of type A.
public static void main(String[] args) {
new B().privateMethod();
A b = new B(); // change here.
b.staticMethod(); // A.staticMethod() is called here.
}
Never speak about static and override in the same sentence.
The whole concept of overridable methods is to dynamically bind at runtime which method is to be executed. Consider this:
class A { void print() { out.println("A"); }
class B extends A { void print() { out.println("B"); }
A obj = new B();
obj.print();
Although the variable obj is of type A, it still prints out "B".
Static methods on the other hand are bound at compile time. This means the compiler uses the type of the variable (or the expression) to determine what method to execute:
class A { static void print() { out.println("A"); }
class B extends A { static void print() { out.println("B"); }
A obj = new B();
obj.print();
This now yields "A". Unfortunately the Java language allows to call static methods on variables or expressions. This is not recommended! Better call static methods on the type itself:
A.print();
B.print();
In the first example - obj.print(); - the compiler automatically translates the statement into A.print(). The actual object does not count. In fact you could write the following:
A obj = null;
obj.print();
Or:
((A) null).print();
That still prints "A".