super.a = b instead of super(b) - java

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; // ***
}
}

Related

Use of super keyword in Java

I have doubt regarding printing of superclass constructor statement even when I have not used super() keyword in subclass.
class A
{
int i;
A()
{
System.out.println("A's constructor");
}
}
class B extends A
{
int i;
B(int a , int b)
{
super.i=a;
i=b;
}
void show()
{
System.out.println(super.i);
System.out.println(i);
}
}
class UseSuper
{
public static void main(String[] args)
{
B b=new B(1,2);
b.show();
}
}
The output of my program is:
A's constructor
1
2
I am unable to understand why I am getting A's constructor printed on my console?
Check the following lines from https://docs.oracle.com/javase/tutorial/java/IandI/super.html
Note: If a constructor does not explicitly invoke a superclass
constructor, the Java compiler automatically inserts a call to the
no-argument constructor of the superclass. If the super class does not
have a no-argument constructor, you will get a compile-time error.
Object does have such a constructor, so if Object is the only
superclass, there is no problem.
If a subclass constructor invokes a constructor of its superclass,
either explicitly or implicitly, you might think that there will be a
whole chain of constructors called, all the way back to the
constructor of Object. In fact, this is the case. It is called
constructor chaining, and you need to be aware of it when there is a
long line of class descent.
I hope, it clears your doubts.
[Update]
Posting this update to clear OP's doubts he has mentioned in his comment below.
The following code won't compile because implicit super constructor A() has not been defined and we have also not defined it explicitly. Note that the implicit super constructor A() is automatically defined when there is no other constructor with arguments have been defined.
class A {
int i;
A(int x,int y){
}
}
class B extends A {
int i;
B(int a, int b) {
super.i = a;
i = b;
}
void show() {
System.out.println(super.i);
System.out.println(i);
}
}
public class UseSuper {
public static void main(String[] args) {
B b = new B(1, 2);
b.show();
}
}
[Another Update]
Posting this update to clear OP's another doubt which he has mentioned in his comment below.
The following code too won't compile because the super constructor A() has been declared as private preventing the child class constructor to call it.
class A {
int i;
private A() {
System.out.println("A's constructor");
}
}
class B extends A {
int i;
B(int a, int b) {
super.i = a;
i = b;
}
void show() {
System.out.println(super.i);
System.out.println(i);
}
}
class UseSuper {
public static void main(String[] args) {
B b = new B(1, 2);
b.show();
}
}
When a class extends another class, it is crucial to first call the constructor of the parent class and initialize it, before calling the constructor of the current class.
Even when not visually calling super() in any part of your constructor, Java itself calls the constructor of class A.
If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass. If the superclass does not have a no-argument constructor, you will get a compile-time error. Object does have such a constructor, so if Object is the only superclass, there is no problem.
In other words, constructor B(int a , int b) calls constructor A() implicitly. In IDE, just change A() to A(int i) and you'll see an error message for constructor B(int a , int b) like "Implicit super constructor A() is undefined. Must explicitly invoke another constructor".

How to change the type of a variable of a super class in a subclass?

I am trying to create a constructor in a subclass, but I want to change one of its "inherited" variables to something more appropriate for the subclass without changing the functionality of the superclass (specifically, I am trying to change the type of the variable from a String to an Object I made in another class). Problem is, I can't directly change or access the variable because it is private in the superclass and there is no setters for this variable.
Is there some other way to effectively override the superclass constructor so I can modify this "inherited" variable without editing the superclass? Or should I not be inheriting from the superclass in this case, even though all the other methods would remain mostly untouched?
Essentially, what I want to do is something like this:
//This should not be changed
public class Super
{
private SomeArrayObject<String> o;
private String a;
private SomeObject b;
public Super(String a, SomeObject b)
{
this.a = a;
this.b = b;
o = new SomeArrayObject<String>();
}
public void someMethod()
{
//Does something
}
}
public class Sub
{
private SomeArrayObject<ObjectFromOtherClass> o; //Notice the diff?
public Sub(String a, SomeObject b)
{
super(a, b);
o = new SomeArrayObject<ObjectFromAnotherClass> o;
}
}
As a quick note, there is no "default constructor" in the superclass, so I can't just use super() and fill in the variables as needed.
I can see your problem. You can't modified it because is private right? and it's ok to be private variable, but in this such of cases, you can change the visibility of the variable to protected, so the subclass can see it and modify it.
Edit:
Seeing the new info, you have to do a few little changes more, add a generic, and makke the variable protected, an create a new generic class:
public class SuperClassGen<A> {
protected ArrayList<A> o;
private String a;
private int b;
public SuperClassGen(String a, int b) {
this.a = a;
this.b = b;
this.o = new ArrayList<A>();
}
}
public class SuperClass extends SuperClassGen<String> {
public SuperClass(String a, int b) {
super(a, b);
}
}
public class SubClass extends SuperClassGen<ObjectFromOtherClass> {
public SubClass(String a, int b) {
super(a, b);
}
}
That will allow change the type from the subclass in the constructor, without

is there a vitual parameter invocation as there is for virtual method invocation in java? [duplicate]

class A
{
int a = 2, b = 3;
public void display()
{
int c = a + b;
System.out.println(c);
}
}
class B extends A
{
int a = 5, b = 6;
}
class Tester
{
public static void main(String arr[])
{
A x = new A();
B y = new B();
x.display();
y.display();
}
}
Why does the output come out as 5,5? And not 5,11?.How would the y.display() method work?
why does the output comes 5,5?
Because A.display() only knows about the fields A.a and A.b. Those are the only fields that any code in A knows about. It looks like you expect the declarations in B to "override" the existing field declarations. They don't. They declare new fields which hide the existing fields. Variables don't behave virtually in the way that methods do - the concept of overriding a variable simply doesn't exist. From the JLS section 8.3:
If the class declares a field with a certain name, then the declaration of that field is said to hide any and all accessible declarations of fields with the same name in superclasses, and superinterfaces of the class.
You can get the effect you want by changing B so that its constructor changes the values of the existing fields that it inherits from A instead:
class B extends A {
B() {
a = 5;
b = 6;
}
}
Note that these are not variable declarations. They're just assignments. Of course in most code (well, most code I've seen anyway) the fields in A would be private, so couldn't be accessed from B, but this is just example for the purpose of explaining the language behaviour.
In class A you declare fields a and b. The method display uses these fields. In class B you declare NEW fields of the same name. You're actually hiding the old fields not "overriding" them. To assign different values to the same fields use a constructor:
class A {
A(int a, int b) {
this.a = a;
this.b = b;
}
A() {
this(2, 3);
}
int a,b;
public void display() {
int c=a+b;
System.out.println(c);
}
}
class B extends A {
B() {
super(5, 6);
}
}
When doing this:
class B extends A
{
int a = 5, b = 6;
}
you are not redefining a and b, you're creating new variables with the same names. So you end up with four variables( A.a, A.b, B.a, B.b).
When you call display() and calculate the value of c, A.a and A.b will be used, not B.a and B.b
There isn's anything called variable overriding. That is why you are getting the same result in both the cases.
The reason is that Java uses the concept of lexical scope for variable resolution.
Fundamentally, there are two possible options to resolve free variables in a function ('free' means not local and not bound to function parameters):
1) against the environment in which the function is declared
2) against the environment in which the function is executed (called)
Java goes the first way, so free variables in methods are resolved [statically, during compilation] against their lexical scope (environment), which includes:
method parameters and local method variables
field declarations in the class containing method declaration
public field declarations in parent class
and so on, up the chain of inheritance
You would see this behaviour implemented in most programming languages, because it is transparent to developer and helps prevent errors with shadowing of variables.
This is opposite to the way methods work in Java:
class A {
public void foo() {
boo();
}
public void boo() {
System.out.println("A");
}
}
class B extends A {
#Override
public void boo() {
System.out.println("B");
}
}
class Main {
public static void main(String[] args) {
B b = new B();
b.foo(); // outputs "B"
}
}
This is called dynamic dispatch: method call is resolved dynamically in runtime against the actual object, on which it is called.
When you compile your code it pretty much becomes like:
class A extends java.lang.Object
{
int a=2,b=3;
public void display()
{
int c=a+b;
System.out.println(c);
}
}
class B extends A
{
int a = 5, b = 6;
public void display()
{
super(); //When you call y.display() then this statement executes.
}
}
class Tester
{
public static void main(String arr[])
{
A x = new A();
B y = new B();
x.display();
y.display();
}
}
And hence, when super calls, the method of class A is being called.
Now go to method of class A. Here int c = a + b; means
c = this.a + this.b; which is 2 + 3.
And the result is 5.
Class B declares variables in B scope, public void display() is part of A class and knows only about its own scope variables.
It's the inheritance functaionality which gives the output 5,5.
Java doesn't have anything like variable overriding. Thus, when the method display() is invoked, it accesses the variables inside the parent class 'A' and not the variables inside the subclass 'B'.
It can be explained with the same reason of why you can't print a variable declared in a subclass (and not in superclass) inside superclass method. The superclass method simply doesn't have access to the subclass variables.
However, you'll be able to print 5,11 if you have accessor methods to the fields in both the classes and you use those accessor methods to get the values instead of directly accessing using variable names. (even if the display() method is present only in superclass). This is because the overridden accessor methods are invoked (in second case) which return the values from the subclass.
Why does the output come out as 5,5? And not 5,11?
Whenever we have same instance variables (applicable to class variable as well) in a class hierarchy, the nearest declaration of the variable get the precedence. And in this case, nearest declaration of a and b from display () method is A’s. So class B’s instance variables go hidden. Hence in both cases, 5 gets printed.
How would the y.display() method work?
Another alternative is to have getter in both classes to get value of a and b.
class A
{
int a = 2, b = 3;
public int getA() {
return a;
}
public int getB() {
return b;
}
public void display()
{
int c = getA() + getB();
System.out.println(c);
}
}
class B extends A
{
int a = 5, b = 6;
public int getA() {
return a;
}
public int getB() {
return b;
}
}
class Tester
{
public static void main(String arr[])
{
A x = new A();
B y = new B();
x.display();
y.display();
}
}
Prints
5
11

In Java , Can't access protected members of super-class from sub-class

class Super {
protected int a;
protected Super(int a) { this.a = a; }
}
class Sub extends Super {
public Sub(int a) { super(a); }
public Sub() { this.a = 5; }
}
public Sub() { this.a = 5; }
this.a=5 doesn't work. Why is this so? Protected and public members should be inherited.
The problem isn't that you access the variable, but that you don't call the base constructor:
class Super {
protected int a;
protected Super(int a) { this.a = a; }
}
class Sub extends Super {
public Sub(int a) { super(a); }
public Sub() {
super(0); // <-- call base constructor
this.a = 5;
}
}
This happens because you didn't define a default constructor for Super, so derived classes don't know which constructor to call if you're not specifying one.
Your parameterless constructor in Sub is attempting to implicitly invoke a parameterless constructor in Super which doesn't exist, which is (I assume) why you're getting a compile error.
What does not work? Works for me...
What you do not have is a default constructor - in public Sub() {this.a = 5; } the parent default constructor is called, which you have not provided. If I compiler your code I get:
cannot find symbol constructor Super()
So you either have to have a default constructor or do: public Sub() { super(5); }

How can I call the constructor of the grand parent class?

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()

Categories

Resources