Java does not allow multiple inheritance, meaning that a class cannot inherit from two classes, which does not have anything in common, meaning that they are not on the same inheritance path. However, a class can inherit from more classes, if these classes are super classes of the direct super class of the class. But the class inherits from these classes indirectly, meaning that it does not "see" anything from these upper super classes, right? I was confused when considering constructors (using super() in the constructor). For example, if we have the following classes:
public class A {
public A() {
....
}
}
public class B extends A {
public B() {
super();
....
}
}
public class C extends B {
public C() {
super();
....
}
}
the constructor of class C invokes first the constructor of class B using super(). When this happens, the constructor of B itself invokes first the constructor of A (with super()), but the constructor of C does not know anything about the constructor of A, right? I mean, the inheritance is only from the direct super class - the first (nearest) class from the inheritance hierarchy. This is my question - with super() we mean only the constructor of the direct super class, no matter how many other classes we have in the inheritance hierarchy.
And this does not apply only for constructors, but for any methods and instance variables..
Regards
You have to invoke some constructor in your immediate base class. This can be
public class A {
public A() {
....
}
public A(String foo) {
....
}
}
public class B extends A {
public B() {
super();
.. or ..
super("ThisIsAB")
}
}
public class C extends B {
public C() {
super();
....
}
}
So for constructors you cannot AVOID constructing your intermediate base classes, but you can choose which constructor to use. If there is only the no-args constructor it's all handled for you with an implicit call to super. With multiple constructors you have some more choices.
super can refer to any non-private variable or method in any base class. So methods and variables are not the same as constructors in this respect.
Even if you could avoid calling the intermediate ctor, you wouldn't want to, because that would mean you had uninitialized pieces of the intermediate classes that might be acessed by the bottom-most derived class. To horrible effects.
But I sense that you're trying to trick your way around Java to do multiple inheritance. That is a Bad Thing. Instead, you can do it Java-wise by using an interface
class B extends A implements C {
// ... implement C methods here
}
or by using aggregation
class B extends A {
private C c;
}
Constructors for all parents are called. In fact, deep down C knows about A because B extends A. For example, if the class A contained method foo(), then you could call foo() from C.
So from your example, C calls the constructor from B, which calls the constructor from A. Additionnally, A also extends from the class Object. So the constructor in the class Object is also called!
Furthermore, you do not need to add a call to super(). If there is no call for the constructor of the parent, super is call implicitly.
As you say, C's constructor invokes B's constructor which invokes A's constructor. You can call any "A" methods on a C object, and a C object can see non-private fields in A.
Even if you override A's method "foo" in C, you can get the A version with "super.foo()", assuming B doesn't also override it.
As far as C knows, anything that it does not overwritten in C is contained in B, even if under the covers class A is where the implementation might be.
public class A {
public A() {
}
public void aMethod() {
}
}
public class B extends A {
public B() {
super();
}
}
public class C extends B {
public C() {
super();
}
public void doWork() {
super.aMethod();
}
}
So in this case A handles the implementation of aMethod(), even though calling super() in C's constructor called B's constructor directly, not A's.
Related
public class A {
public A() {
System.out.println("A");
}
}
public class B extends A{
public B() {
System.out.println("B");
}
}
public static void main(String[] args){
B b1 = new B();
Output:
A
B
So what's confusing me is, the Inheritance documentation of Java states that:
Constructors are not members, so they are not inherited by subclasses,
but the constructor of the superclass can be invoked from the
subclass.
From my understanding of that, unless you specifically call for super() in the constructor of class B, it should not print A.
So the question is, why does it print A?
The compiler calls the default constructor (no-arg constructor) of the superclass initially from the subclass constructor. So you don't need to explicitly call it. That's why the line is getting printed above.
If you want to call non-default constructor (constructor with arguments) of superclass, then you would have to explicitly call it form subclass.
If constructors do not inherits in Java, why do I get compile error(Implicit super constructor A() is not visible for default constructor. Must define an explicit constructor)?
class A {
private A() {
}
}
public class B extends A {
}
UPD. I know that super() is called in implicit B constructor. But i don't get why it can't access private constructor with super(). So, if we have only private constructors, class de facto is final?
if B extends A, B must have an access to an A constructor.
Keep in mind that a constructor always call super().
So here, the implicit parameterless constructor of B can't call the A constructor.
In Java, if you create an instance of Child Class, Parent Class instance gets created implicitly.
So Child Class constructor should be visible to Child Class as it calls the constructor of Parent Class constructor using super() in the first statement itself.
So if you change the constructor of the Parent Class to private, Child Class could not access it and could not create any instance of its own, so compiler on the first hand just does not allow this at all.
But if you want to private default constructor in Parent Class, then you need to explicitly create an overloaded public constructor in the Parent Class & then in Child class constructor you need to call using super(param) the public overloaded constructor of Parent Class .
Moreover, you might think then what's the use of private constructors. private constructors is mostly used when you don't want others from any external class to call new() on your class. So in that case, we provide some getter() method to provide out class's object.In that method you can create/use existing Object of your class & return it from that method.
Eg. Calendar cal = Calendar.getInstance();. This actually forms the basis of Singleton design pattern.
The important point is to understand that the first line of any constructor is to call the super constructor. The compiler makes your code shorter by inserting super() under the covers, if you do not invoke a super constructor yourself.
Now if you make that constructor in superclass private, above mentioned concept will fail.
Your class B has a default constructor, B() - because you didn't explicitly define any other one.
That constructor implicitly calls its super constructor, A().
But you have explicitly made that one private to class A, so you have explicitly declared that no other class, including B, can have access to it.
Can work
class A {
private A() {
}
public A(int i){
}
}
public class B extends A {
private A(){
super(10);
}
}
Or remove the private A(), defaults to public A(),
unless you have another constructor
class A {
}
public class B extends A {
private A(){
super();
}
}
An instance of class B creates an instance of class A so B must invoke super(...) if A implements a non default constractor. So the constructor should be protected for B being able to call super(...)
public class B extends A {
/*
* The default constructor B means
* public () B {super();}
*/
public B() {
}
}
So you should define a constructor which is accessible by the class B
You can change the access modifier for parent Constructor
Or else you can define other Constructor in parent class which is accessible by class B and call that constructor.
Suppose there are three classes A, B and C. C extends B and B extends A. Can we call class A constructor directly without calling class B constructor in sub class C?
No. The constructor of a subclass will explicitly or implicitly invoke one of the constructors of its superclass to initialize itself. Constructors of other classes cannot be invoked (except to initialize different objects) whatever those classes' relationship to the class being initialized may be.
I don't think that is possible.
Anyways, if C does not relate to B, but to A, why does C extend B in the first place?
You could also try and create some protected method in A that could be called from both A's and C's constructors.
If you could try and describe what you're trying to model, maybe some alternative hierarchy would be more suitable.
No you can't, although the constructor of child class starts executing first(when you create its object) but there's always a no-arg constructor call to super in the constructor of the child(unless you manually call super with arguments) and so on. Following this hierarchy the constructor of the top most parent class although starts its execution at last, but finishes first!
Not directly .. but something like this can be done:
public class A {
A(){
....
}
}
public class B extends A {
B(){
super();
....
}
}
public class C extends B {
C(){
super();
....
}
}
// In main()
C c = new C(); // This will eventually call A's constructor
I have another question on constructors. I have a hierarchy of more than 2 layers, Say
A,
B extends A,
C extends B.
Can I get constructors from all three layers to fire when I create an instance of C? What if I want to pass super(int anArgumentForA, int anArgumentForB); Is that even possible? Seems like that's where it's going but I don't find a way to differentiate the arguments going to A vs B. Default constructor from B seems to run and I can't feed it the value it needs in order to run a different constructor because I don't know how.
You can have each layer call super(...) to set the information in each layer.
public Class A
{
public A(Object a, Object b)
{
//do any initialization needed
}
}
public Class B extends A
{
public B(Object a, Object b, Object c)
{
super(a, b); //This will call A(a, b)
//do any initialization needed
}
}
public Class C extends B
{
public C(Object a, Object b, Object c)
{
super(a, b, c); //This will call B(a, b, c)
//do any initialization needed
}
}
Keep in mind I don't think it is advisable to use these constructors to set the Objects to a variable at each level. So you don't want to have the constructors for A, B, and C each set some object Object x = a in the constructor. Only one, at most, level in the hierarchy should maintain a reference to the Objects being passed into the constructors.
In the world of Java, when you are extending another class, you only see your direct super class' constructor. The super class is supposed to proper encapsulate the super-super class constructor.
That means, in your case, B should provide a constructor that proper encapsulate A. In case B cannot determine the argument to pass to A's constructor, it is reasonable to ask for it in B's own constructor:
class A {
A (int aArg) {
// init base on aArg
}
}
class B extends A {
B (int aArg, int bArg) {
super(aArg);
// extra initialization base on bArg and aArg
}
}
class C extends B {
C() {
super(SOME_A_ARG, SOME_B_ARG);
}
}
As per Java Specification the constructors are not inherited by sub-classes.
So, as per you requirement you should keep in mind that the super class should have scope to pass objects.
When you are declaring a class by extending another class B extends A and C extends B , you should define the constructor
such a way so that you can customize that for initialization . This declaration always depends on the depth and hierarchy of the
inheritance .
class A{
A(Object firstObj, Object secondObj){
//Do you stuff for initialization
}
}
class B extends A{
//Keep in mind that this B class will be inherited by other class
B(Object firstObj,Object secondObj,Object thirdObj){
//Call super class constructor
super(firstObj,secondObj);
//Do other initialization stuff here
}
}
class C extends B{
//Keep in mind that this C class will be inherited by other class
C(Object firstObj,Object secondObj,Object thirdObj){
//Call super class constructor
super(firstObj, secondObj, thirdObj); //call constructor of B
//Do other initialization stuff here
}
}
It always depends how you parent class constructor has defined. It depends on the number of parameter passes to parent class constructor, you need to call accordingly from child class constructor.
Hope it will help you.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Use of ‘super’ keyword when accessing non-overridden superclass methods
I'm new to Java and have been reading a lot about it lately to get more knowledge and experience about the language. I have a question about inherited methods and extending classes when the compiler inserts automatic code.
I've been reading that if I create class A with some methods including lets say a method called checkDuePeriod(), and then create a class B which extends class A and its methods.
If I then call the method checkDuePeriod() within class B without using the super.checkDuePeriod() syntax, during compilation will the compiler include the super. before checkDuePeriod() or will the fact that the compiler includes the super() constructor automatically when compiling the class imply the super. call of the methods that class B calls from class A?
I'm a little confused about this. Thanks in advance.
The super class's implementation of regular methods is not automatically invoked in sub classes, but a form of the super class's constructor must be called in a sub class's constructor.
In some cases, the call to super() is implied, such as when the super class has a default (no-parameter) constructor. However, if no default constructor exists in the super class, the sub class's constructors must invoke a super class constructor directly or indirectly.
Default constructor example:
public class A {
public A() {
// default constructor for A
}
}
public class B extends A {
public B() {
super(); // this call is unnecessary; the compiler will add it implicitly
}
}
Super class without default constructor:
public class A {
public A(int i) {
// only constructor present has a single int parameter
}
}
public class B extends A {
public B() {
// will not compile without direct call to super(int)!
super(100);
}
}
If you call checkDuePeriod() in B without super., means you want to invoke the method that belongs to the this instance (represented by this within B) of B. So, it equivalent to saying this.checkDuePeriod(), so it just doesn't make sense for the compiler to add super. in the front.
super. is something that you must explicitly add to tell the compiler that you want to call the A's version of the method (it is required specially in case B has overridden the implementation provided by A for the method).
Call of super() as a default constructor (constructor with no args) can be direct or non direct but it garants that fields of extendable class are properly initialized.
for example:
public class A {
StringBuilder sb;
public A() {
sb = new StringBuilder();
}
}
public class B extends A {
public B() {
//the default constructor is called automatically
}
public void someMethod(){
//sb was not initialized in B class,
//but we can use it, because java garants that it was initialized
//and has non null value
sb.toString();
}
}
But in case of methods:
Methods implement some logic. And if we need to rewrite logic of super class we use
public class B extends A {
public B() {
}
public boolean checkDuePeriod(){
//new check goes here
}
}
and if we want just implement some extra check, using the value returned from checkDuePeriod() of superclass we should do something like this
public class B extends A {
public B() {
}
public boolean checkDuePeriod(){
if(super.checkDuePeriod()){
//extra check goes here
}else{
//do something else if need
}
return checkResult;
}
}
First about the Constructors:
- When ever an object of a class is created, its constructor is initialized and at that time immediately the constructor of its super-class is called till the Object class,
- In this process all the instance variables are declared and initialized.
- Consider this scenario.
Dog is a sub-class of Canine and Canine is a sub-class of Animal
Now when Dog object is initialized, before the object actually forms, the Canine class object must be form, and before Canine object can form the Animal class object is to be formed, and before that Object class object must be form,
So the sequence of object formed is:
Object ---> Animal ---> Canine ---> Dog
So the Constructor of the Super-Class is Called before the Sub-Class.
Now with the Method:
The most specific version of the method that class is called.
Eg:
public class A{
public void go(){
}
}
class B extends A{
public static void main(String[] args){
new B().go(); // As B has not overridden the go() method of its super class,
// so the super-class implementation of the go() will be working here
}
}