How can we call the constructor of grand parent.
eg: B inherits from A and C inherits from B.
I need to call the constructor of A in C. Is it possible without creating an instance of B?
If i need this how this can be implemented in Java.
You can't invoke the constructor of A directly in the constructor of C.
You can (and actually must) call it indirectly, 'though. Each constructor of B has to call a constructor of A (either explicitly or implicitly). Since every constructor of C needs to call one of the constructors of B you will always call one of As constructors.
use super() from C and from B to access A's constructor
class A {
public A() {
System.out.println("A");
}
}
class B extends A {
public B() {
super();
System.out.println("B");
}
}
class C extends B {
public C() {
super();
System.out.println("C");
}
}
public class Inheritance {
public static void main(String[] args) {
C c = new C();
}
}
Output :
A
B
C
Note:
If all are default constructor then no need to write super(); it will implicitly call it.
If there is parametrized constructor then super(parameter.. ) is needed
C will have to call B's constructor and in turn B will call A's constructor...
there is No other option to call Grand parent's constructor
An example to Joachim's answer:
class A {
A() { System.out.print("A()")};
A(Object o) { System.out.print("A(Object)")};
}
class B {
B() { super(); System.out.print("B()")};
B(Object o) { super(o); System.out.print("B(Object)")};
}
class C {
C() { super(); System.out.print("C()")};
C(Object o) { super(o); System.out.print("C(Object)")};
}
Now calling:
C c = new C();
will produce: A()B()C(), while calling:
C c = new C(new Object());
will produce: A(Object)B(Object)C(Object).
As you can see, by manipulating super() call you can actually call explicit parent constructor.
Actually, if you have class B extending class A, you can't avoid to call the constructor method for A when you create an instance of the class B. If this mechanism doesn't seems clear to you, I recommend this reading about Java's inheritance system: http://download.oracle.com/javase/tutorial/java/IandI/subclasses.html .
Here's an example:
class A {
public A() {
doSomethingA();
}
}
class B extends A {
public B() {
super(); // this is the call to the A constructor method
doSomethingB();
}
}
class C extends B {
public C() {
super(); // this is the call to the B constructor method
doSomethingC();
}
}
Creating a new object with new C() will involve, in order, the calling of A() - B() - C()
Related
I'm learning the super keyword and accidentally get this, here's an example :
public class A {
double a;
public A (double a) {
this.a = a;
}
}
public class B extends A {
public B (double b) {
super.a = b; //***
}
}
The usual way to do this as in the tutorials is super(b) to reusing its parent constructor, but what is wrong with super.a = b?
There is no "constructor inheritance" in Java. If the super class doesn't have a no-arg constructor, you must explicitly call its constructor (or one of them if there are several). If you don't, you'll get a compilation error.
When you write your class A like this:
public class A {
double a;
public A(double a) {
this.a = a;
}
}
you overwrite the default constructor and in the line this.a = a you are accessing instance variable and setting the values and in class B:
public class B extends A {
public B(double b) {
super.a = b; // ***
}
}
you are trying to access instance variables of Class B through the constructor because super.a in here , the super referes to the constructor and its wrong and throwing the Implicit super constructor A() is undefined. Must explicitly invoke another constructor which means: in Class B its looking for a constructor which has no parameter because you overwrite the default constructor of class and it can't recognize it by calling super.a = b so you have to call the super constructor as a function and in the first line of code:
public class B extends A {
public B(double b) {
super(b);
super.a = b; // ***
}
}
If we have 2 classes like this :
public class A {
public static int m=10;
public int b(){ m++; return m;}
public int fun() {
return b();
}
}
public class Testfun() extends A {
#Override
public int b() {return 1;}
public void test(){
A a = new A();
assertEquals(1,a.fun());
}
}
Is there any way to make the method fun() in class A call the overriden b() instead of the its super b()?
The idea is:
I suppose to test the method fun() and do a stub b(). So I don't want the method to call the original b() and call the stub one.
Is there any way to make the method fun() in class A call the overriden b() instead of the its super b() ?
No way. The instance you have is of type A and methods from A gets called. Period.
No you can not call.The instance you have is of type A and methods from A gets called.
No, it's not possible, because object don't know how many of it's childs or are there any of it. When you want to test something inside a class and want to stub it it's signal of you need to make it dependency of the class like this:
public class A {
private final B b;
public A(B b) {
this.b = b;
}
public int fun() {
return b.b();
}
}
public interface B {
int b();
}
public class Testfun() {
public void test(){
B b = new B {
public int b() {
return 1;
}
};
A a = new A(b);
assertEquals(1, a.fun());
}
}
In this example we make B as dependency of class A and able to change B from desirable implementation in runtime to test dummy in testing. When you need to test B itself you need separate class that tests B. See https://en.wikipedia.org/wiki/Strategy_pattern
Thanks for all, it really helped me !
My mistake was here
A a = new A();
It should be :
A a = new Testfun();
Therefor the overriden b() will be called.
public class Temp {
public static void main(String args[]) {
A ref;
B objB = new B();
C objC = new C();
ref = objB;
ref.show();
ref = objC;
ref.show();
}
}
abstract class A {
abstract void show();
{
System.out.println("In Class A");
}
}
class B extends A {
void show() {
System.out.println("In class B");
}
}
class C extends B {
void show() {
System.out.println("In Class C");
}
}
In the above code abstract methods containing a definition of the method. But in books it is stated that an abstract method should contain only the declaration rather definition of that method. When i execute this program it results in the following output without any error. Please explain me how it shows the below output.
In Class A
In Class A
In class B
In Class C
Your abstract class does not contain a definition of the method. Your abstract class contains an abstract method, and an initializer block.
abstract class A {
// Abstract method
abstract void show();
// Initializer block, completely unrelated to show
{
System.out.println("In Class A");
}
}
Initializer blocks run when the object is constructed - similarly to constructors (but you can have more than one, and they can't have arguments). It's exactly the same as if you wrote:
abstract class A {
// Abstract method
abstract void show();
// Constructor
public A()
{
System.out.println("In Class A");
}
}
The output comes from:
A ref;
B objB = new B(); // calls B's constructor, then A's constructor which prints "In Class A"
C objC = new C(); // calls C's constructor, then A's constructor which prints "In Class A"
ref = objB;
ref.show(); // prints "In Class B"
ref = objC;
ref.show(); // prints "In Class C"
This abstact method has no implementation in class A:
abstract void show();
The semi-colon ends the method declaration without an implementation.
The following block is an instance initialization block (which gets executed when creating an isntance of the class, before the code of the constructor is executed), unrelated to the abstract method :
{
System.out.println("In Class A");
}
If you tried to give an implementation to an abstract method, it would look like this and fail to compile :
abstract void show()
{
System.out.println("In Class A");
}
As for the output you got :
In Class A // new B() causes the instance initialziation block of A to be executed before the (default) constructor of A
In Class A // new C() causes the instance initialziation block of A to be executed before the (default) constructor of A
In class B // first ref.show() executes B's show, since you assigned objB to ref
In Class C // second ref.show() executes C's show, since you assigned objC to ref
I have class In java: A. And class B which extends class A.
Class A hold instance of class B.
I notice that when I call the constructor of class B (when I init this parameter in class A), It does super(), create a new instance of A and init all it fields.
How I can tell class B that the concrete instance of class A (which init it field) - it his parent class?
Your question is really hard to understand, but I guess the problem is this this (your approach):
public class A {
public B b = new B();
}
public class B extends A {
}
So, when you run new A() you get a StackOverflowError.
In my practical experience, I never needed a design like that, and I'd strongly recommend to re-think your approach. However, if it is really needed, you could use a dedicated init() method, e.g.:
public class A {
public B b;
public void init() {
b = new B();
}
}
A a = new A();
a.init();
If you needed A within B you could just do it with a custom constructor for B:
class B extends A {
A a;
public B() {
super();
this.a = this;
}
}
This case is harder though so you need:
class A {
B b;
}
class B extends A {
public B() {
super();
b = this;
}
}
Note that you should not pass the B into the call to super() as B will not be initialized, you should do it as the last step in the constructor of B.
I'll start with a code example:
class A {
public A() {
f(); //When accessed through super() call this does not call A.f() as I had expected.
}
public void f() {} //I expect this to be called from the constructor.
}
class B extends A {
private Object o;
public B() {
super();
o = new Object(); //Note, created after super() call.
}
#Override
public void f() {
//Anything that access o.
o.hashCode(); //Throws NullPointerException.
super.f();
}
}
public class Init {
public static void main(String[] args) {
B b = new B();
}
}
This program throws a NullPointerException. When the object b enters the constructor of its superclass A and makes a call to the method f() which is overridden by the class B B.f() is called, instead of A.f() which I would have expected.
I thought a superclass wasn't supposed to know if it was subclassed or not but surely this can be used by a class to tell if it's been subclassed or not? What's the reason behind this? Is there any workaround if I really want A.f() to be called instead of B.f()?
Thanks in advance.
Follow up question:
Thanks for the answers. I now understand why it is like it is, but here's a follow up question. Perhaps I'm mistaken but a principle of subtyping is that the supertype should not know that it's been subtyped. This "mechanism" lets a class know if it's been subclassed or not. Consider this code example:
class A {
private boolean isSubclassed = true;
public A() {
f(); //A.f() unsets the isSubclassed flag, B.f() does not.
if(this.isSubclassed) {
System.out.println("I'm subclassed.");
} else {
System.out.println("I'm not subclassed.");
}
}
public void f() {
this.isSubclassed = false;
}
}
class B extends A {
public B() {
super();
}
#Override
public void f() {}
}
public class Init {
public static void main(String[] args) {
new B(); //Subclass.
new A();
}
}
The output of this program is:
I'm subclassed.
I'm not subclassed.
Here A knows it's been subclassed. It's unkown by whom but that doesn't matter. How is this explained? Am I misinformed?
The NullPointerException occurs because when you construct an instance of B, the parent constructor (in A) is invoked. This constructor calls the f() method but since the actual type of the object is B, the overridden f() method in B is invoked.
#Override
public void f() {
//Anything that access o.
o.hashCode(); //Throws NullPointerException as o has not been initialised yet
super.f();
}
The lesson here is never to call a method in a constructor which can be overridden by a subclass.
This is why you shouldn't call non-private methods from constructors. There is no workaround, except making the method private.
This is the reason that override hide the own method. At the call of f() at super class constructor, it hide super class method call. Actually it is call to subclass overided method.
class A{
public A() {
f(); // It call the subclass overided method.
}
// This method is hide due to override.
public void f() {
}
}
class B extends A {
// This method is called before constructor where Object o is Null, hence you
// got NullPointerExcetion.
#Override
public void f() {
// Anything that access o.
o.hashCode(); // Throws NullPointerException.
super.f();
}
}
class A {
public A() {
System.out.println(1);
f();
// where super(),this will be called by subclass ,but subclass's o is null
}
public void f() {
System.out.println(4);
}
}