I'm running over this problem while working with the following inheritance and JDK 14
interface A {
default void a() {
System.out.println("default a");
}
default void b() {
System.out.println("default b");
}
}
class AImp implements A {
#Override
public void a() {
System.out.println("a from AImp");
}
#Override
public void b() {
System.out.println("b from AImp");
this.a();
}
}
class B extends AImp {
#Override
public void a() {
System.out.println("a from B");
}
#Override
public void b() {
System.out.println("b from B");
super.b();
}
}
when I run
B b = new B();
b.b();
console gives
b from B
b from AImp
a from B
How come the keyword this in the AImp is referencing the instance of class B?
Am I being confused with something here?
Thank you for spending time.
You have created an instance of B, it is it's dynamic type and due to dynamic binding always the method declared in B is called, because it overrides from A.
It does not matter from where you call the method, but it matters, what is the dynamic type.
With super.method() it is different, it explicitly goes up in the inheritance.
Note: constructors are not overriden, ever. So calling this(params) will not delegate to subclass.
Related
Here's something I quite understand:
abstract class A {
public void foo() {
System.out.println("a");
}
}
abstract class B extends A {
#Override
public abstract void foo();
public void bar() {
super.foo();
foo();
}
}
class C extends B {
#Override
public void foo() {
System.out.println("c");
}
}
public static void main(String[] args) {
new C().foo();
new C().bar();
}
new C().foo() prints c to the console, while new C().bar() prints a then c.
Calling super.foo() is illegal in the #foo() implementation of the C class.
I don't have a clear question, but if anyone could give a complete explanation of what is going on with the foo method, it may be interesting I think.
A is super class for B, so calling super.foo() inside B calls method defined in A, and calling foo() inside the same class will invoke its own implementation that should be delivered by any subclass.
You cannot use super.foo() within C class because it is defined as abstract in B and cannot be invoked directly.
I have a little confusion in Java overriding. Suppose we have the following inheritance:
class A{
public A(){
}
void show(){
System.out.println("SuperClass");
}
}
class B extends A{
#Override
void show(){
System.out.println("SubClass");
}
}
public class Test {
public static void main(String[] args) {
B b = new B();
b.show();
}
}
Clearly, class B overrides the method show() that is inherited by the class A. Why is not b.show(); printing the message System.out.println("SuperClass"); as well since class B has now the method show() from class A?
Thank you.
The show method of class B overrides the show method of class A and doesn't call it, so there's no reason for System.out.println("SuperClass"); to be executed when you call show on an instance of B.
If you change class B to :
class B extends A
{
#Override
void show(){
super.show ();
System.out.println("SubClass");
}
}
calling show on an instance of B will also execute the logic of A's show method.
In class B you are overriding, in other words replacing the original implementation of the show() method. Every time you invoke show() on an object that is instanceof B that version of the method will be called.
The only way to refer to the original show() method is to refer to it using the super.show() syntax inside B or any other class that extends A.
And as an additional note, that #Override annotation is just to add additional compiler checks but it's not required to actually override a method, you just need to re-implement it as you have done in B.
its the matter of polymorphism which acts , i.e., method call to method body happens at run time i.e when JVM invokes B b=new B(); so B object is of type class B ,so the method it displays B's method which is overridden one, if you put super() in B()'s constructor you can get parents one.
This is the effect of overriding in inheritance. You just replace the method from the superclass (but you can still reach the old one!) Here I also added a little bit with polymorphism too. Hope that this will help you.
class A{
public A(){
}
void show(){
System.out.println("SuperClass");
}
}
class B extends A{
void superclass() {
super.show();
}
#Override
void show(){
System.out.println("SubClass");
}
}
public class Test {
public static void main(String[] args) {
B b = new B();
b.show(); //SubClass
b.superclass(); //SuperClass
A a = new A();
a.show(); //SuperClass
A c = new B();
c.show(); //SubClass
//c.superclass(); //error! the program won't compile
}
}
what will be the flow of execution in case of override? What i believe is , when we call a constructor/object of any class, during execution first it call parent constructor and than child. but what will happen in case of over ridding?
lets suppose:
class A {
public A(){
printStatus();
}
public void printStatus(){
System.out.println("In Class A");
}
}
class B extends A{
public B(){
printStatus();
}
#Override
public void printStatus(){
System.out.println("In Class b");
}
}
public class Test2 {
public static void main(String[] args){
B b = new B();
}
}
Out put of this code is:
In Class b
In Class b
what i don't understand is, why it's printing "In Class be" only, it should be "In class A and, In Class b",
when i remove override method from class b. it give me desired output.
All java methods are virtual. It means the method is called with using actual type of this. So inside of constructor A() {} this is the instance of B, so that is why you've got its method call.
Calling like this printStatus() will call the method from the same class. If you call with super.printStatus() it will envoke method from the super class (class which you have extended).
When you over-ride a method you over-ride it completely. The existence of the original implementation is completely invisible to other classes (except via reflection but that's a big topic of its own and not really relevant). Only your own class can access the original method and that is by calling super.methodName().
Note that your class can call super.methodName() anywhere, not just in the overriding function, although the most usual use for it is in the overriding function if you want the super implementation to run as well as your own.
Constructors are a slightly special case as there are rules about how and why constructors are called in order to make sure that your super-class is fully initialized when you try and use it in the inheriting class.
super is always called whether you write super(); or not.
In the example printStatus() method of Class A will never be called. Since you are creating an instance of class B and there will be method overriding. You can use the following to call the Class A printStatus() method.
public B()
{
super.printStatus();
}
When you override a method, it will override the one that you expect from class A.
Should use super keyword for calling super class method.
class A {
public A(){
printStatus();
}
public void printStatus(){
System.out.println("In Class A");
}
}
class B extends A{
public B(){
super.printStatus();
}
#Override
public void printStatus(){
System.out.println("In Class b");
}
}
Constructor public B(){ super.printStatus(); } calls Class A print method and constructor public A(){ printStatus(); } calls Class B print method since you've overridden.
But its wrong with overridable method calls in constructors.
Try with like this :
class A {
public A(){
printStatus();
}
public void printStatus(){
System.out.println("In Class A");
}
}
class B extends A{
public B(){
super.printStatus();
printStatus();
}
#Override
public void printStatus(){
System.out.println("In Class b");
}
}
public class Test2 {
public static void main(String[] args){
B b = new B();
}
}
For better understanding the concepts of Overloading and Overriding just go through this links:
http://en.wikibooks.org/wiki/Java_Programming/Overloading_Methods_and_Constructors
Consider the following code classes.
public class A
{
public A()
{
callCreation();
}
protected void callCreation()
{
System.out.println("A Created!!");
}
}
public class B extends A
{
protected void callCreation()
{
System.out.println("B Created!!");
}
}
public class C extends B
{
protected void callCreation()
{
System.out.println("C Created!!");
}
public static void main(String[] args)
{
A a = new A();
A b = new B();
A c = new C();
}
}
The output of running the class C is given below.
A Created!!
B Created!!
C Created!!
The first output line in the output A Created!! is printed because when the constructor of class A is called, it calls the super class's constructor (java.lang.Object) implicitly before calling the callCreation() method in the class A's constructor. And this will be the case for B and C classes too. In that case when the constructor of B is called the call flow should be typically : B's constructor -> A's Constructor -> java.lang.Object's Constructor -> come back to A's callCreation() method to finish calling A's constructor. If so how is the overridden value printed and not the super class's value is printed? So the question is 'when is an object of a class created exactly? to put it in other words, the object of a class should be created only after the constructor finishes calling/initializing all the elements within itself. If so how can a method be called from a child class and not from the parent class?
The callCreation methods in B and C override the method from A. So when the method is called in the constructor A the implementations in B and C will be run, even though the constructors of B and C have not been executed yet. This is possible because constructors don't actually create the object, rather they are called to initialize some moments after the JVM has created it.
In general it's a very bad idea to call methods that can be overridden from a constructor for this very reason. A method in B or C may assume that the constructor and object initializers have already been run, and read an unexpected value from a field. For example the following ends up printing "B Created!! null" because the field still has not be assigned its value.
public class B extends A
{
final String msg = "Yes!";
protected void callCreation()
{
System.out.println("B Created!! "+msg);
}
}
thinking in this way makes it more obvious:
when an object of type B is being created super() keyword calls the A constructor,
then in A constructor "this.callCreation()" is executed, which refers to the current
object which is B, so callCreation corresponding to the current object(B) is called.
the same process is done for C.
public class A {
public A() {
this.callCreation();
}
protected void callCreation() {
System.out.println("A Created!!");
}
}
class B extends A {
public B() {
super();
}
protected void callCreation() {
System.out.println("B Created!!");
}
}
class C extends B {
public C() {
super();
}
protected void callCreation() {
System.out.println("C Created!!");
}
public static void main(String[] args) {
A a = new A();
A b = new B();
A c = new C();
}
}
Here are two examples:
public class A {
public void foo(A a) {
System.out.println("in A");
}
}
public class B extends A {
public void foo(B b) { // (1)
System.out.println("in B");
}
public void f(Object o) { // (2)
System.out.println("in B");
}
}
I don't understand how come (1) and (2) are considered to be an overrided method for A's foo(). method number 1 accepts a lower class than the original foo(), I mean that I can't send her any class of A. as I see it, (1) does not extend foo(), but it is still counts as an override- why?( Similar argument for (2), but opposite).
The reason that I made me think that it is overrided is this:
when I'm trying to run
B b = new B();
b.foo(b);
It checks if A has a foo that accepts B. since every B is an A, it does have one so it ought to print "in A" and not "in B" because B does not overrides it. but it prints "in B"..
Neither of them override the super class A'a method.
class A {
public void foo(A a) {
System.out.println("in A");
}
}
class B extends A {
#Override
public void foo(B b) {
System.out.println("in B");
}
#Override
public void foo(Object o) {
System.out.println("in B");
}
}
When I compile the above I get errors:
$ javac -g O.java
O.java:10: method does not override or implement a method from a supertype
#Override
^
O.java:14: method does not override or implement a method from a supertype
#Override
^
2 errors
But note that it is ok to return a subclass from an overriding method. The following compiles without error.
class A {
public A foo() {
System.out.println("in A");
return this;
}
}
class B extends A {
#Override
public B foo() {
System.out.println("in B");
return this;
}
}
For overriding to work, method signatures should be the same. In this case, they aren't because they differ in the arguments they take. They are just member functions with 1,2 being overloads. ( Considering 2 as a typo. It should be foo instead of f )
Neither 1) nor 2) override anything, as you can verify that by adding the #Override annotation:
public class B extends A {
#Override
public void foo(B b) {
System.out.println("in B");
}
#Override
public void f(Object o) {
System.out.println("in B");
}
}
Neither method will compile, since it doesn't override anything.