Can't understand Java inheritance - java

i'm studying java as first language, so i'm a complete newbie.
I'm now studying inheritance between classes, and there's something i can't understand. I give you an example:
This is the main class:
public class Bici {
protected int misura;
protected String modello;
public Bici(int misura, String modello)
{
this.misura=misura;
this.modello=modello;
}
public void stampaCaratteristiche()
{
System.out.println("Size is: "+misura);
System.out.println("Model is: "+modello);
System.out.println();
}
}
This is the subclass:
public class Tandem extends Bici {
private int ruote;
public Tandem (int ruote)
{
super(misura, modello);
this.ruote=ruote;
}
public void stampaCaratteristicheTandem()
{
System.out.println("Le ruote del tandem sono "+ruote);
}
}
but when declaring super variables i get this error:
"Cannot refer to an instance field modello while explicitly invoking a constructor"
Why? Thank you!

you do not have default constructor in Bici class, it means in Tandem class it has to be invoked explicitly. like this :
private int ruote;
public Tandem (int ruote, int misura, String modello)
{
super(misura, modello);
this.ruote=ruote;
}
public void stampaCaratteristicheTandem()
{
System.out.println("Le ruote del tandem sono "+ruote);
}
A superclass constructor must execute before a subclass constructor. So that the state and behavior defined by the superclass may be correctly and completely initialized before a subclass constructor executes.
Java compiler assumes that the first line of every constructor is an implicit call to the default superclass constructor unless you explicitly use super() or this().
Note that Super keyword is used to explicitly invoke a superclass constructor. If you use this form, it must appear as the first statement of the constructor to ensure that the superclass constructor executes before the subclass constructor
The Java inheritance mechanism does not include constructors. In other words, constructors of a superclass are not inherited by subclasses. Subclasses can still call the constructors in the superclass using the super() contruct. In fact, a subclass constructor is required to call one of the constructors in the superclass as the very first action inside the constructor body. You may have seen Java classes where the subclass constructors did not seem to call the constructors in the superclass. Maybe the superclass did not even have a constructor. However, the subclass constructors have still called superclass constructors in those case. You just could not see it. Let me explain why:
If a class does not have any explicit constructor defined, the Java compiler inserts an implicit no-arg constructor. Thus, a class always has a constructor.

This is because you can not call an instance method before the instance is created. By the way, it is possible to call an instance method later on in the constructor.
This solve your problem:
public Tandem (int misura, String modello, int ruote){
super(misura, modello);
this.ruote=ruote;
}

Related

What does "extends" actually do?

I am currently studying the concept of "class abstraction" and "extension" and have been wondering:
"If I declare a parametrized constructor inside my abstract class why won't extension on another class work unless I declare myself the constructor with the super keyword invoking the parameters of the abstract class's constructor?"
I understand the fact that extension instances the previous abstract class into the extended one and tries to call the default constructor but have been wondering why it gives out an error.
Is it because the constructor has been parametrized or simply because the empty constructor does not exist?
Does the extends keyword call something along the lines of this?
Object myClass = new AbstractClass();
And the missing parameters are the reason why it gives out an error so something along the lines of this would be correct
Object myClass = new AbstractClass(int foo,float boo);
And if that is it, does the super keyword essentially, if you'll allow me the term, "put" the parameters given in the parenthesis "inside" the constructor?
If that's not it what am I getting wrong? How does it actually work?
You should think of the extends keyword, in this context, as just saying that a class is the subclass of another class, and does nothing else. And that there are rules governing how subclasses and superclasses should work.
When you construct a subclass, you must construct its superclass first. For example, to create a Bird, you must first create an Animal. That makes sense doesn't it? To demonstrate this in code:
class Animal {
public Animal() {
System.out.println("Animal");
}
}
class Bird extends Animal {
public Bird() {
System.out.println("Bird");
}
}
Doing new Bird() will first print Animal and then Bird, because the Animal's constructor is called first, and then the Bird constructor. So actually, the Bird constructor implicitly calls the superclass' constructor. This can be written as:
public Bird() {
super();
System.out.println("Bird");
}
Now what happens if the super class does not have a parameterless constructor? Let's say the constructor of Animal now takes a String name as argument. You still need to call the superclass' constructor first, but super() won't work because super() needs a string parameter!
Therefore, the compiler gives you an error. This can be fixed by calling super() explicit with a parameter.
"If I declare a parametrized constructor inside my abstract class why
won't extension on another class work unless I declare myself the
constructor with the super keyword invoking the parameters of the
abstract class's constructor?"
Because the super class says that it MUST be constructor using that declared constructor and there is no other way around. This applies to every extending class - required constructor must be called.
The same happens with any class when you declare other constructor than default one. For example, having
public class A{
//no default no-arg ctor here
public A(String name){
....
}
}
public class B{
//default no-arg ctor will be created
}
so then
B b=new B();
A a=new A(); //// INVALID!
A a=new A("foobar"); // yeah that is it
The same applies when you are extending classes. To construct child instance, you must first "internally create parent instance" calling super.constructor. Since there is no default constructor, ANY of explicit declared superconstructors must be used.
When initializing an Object the constructor will always be called. Even if you do not define one constructor there will be a default one without any parameters. So if you define a constructor in the abstract class, you have to call that constructor with super().
If you do not define any constructors, then it will be implicitly called as the default one.
If I declare a parametrized constructor inside my abstract class why won't extension on another class work unless I declare myself the constructor with the super keyword invoking the parameters of the abstract class's constructor?
There is no default constructor available in AbstractClass since you define a parametrised constructor. If you don't define a constructor yourself, a default constructor without arguments is implicitly created. You can manually add such one now or you need to use the only available constructor (which is parametrised) with super().
Example of your code with defining constructor without arguments:
class AbstractClass {
AbstractClass() {} // added manually since not created implicitly
AbstractClass(int foo, float boo) {}
}
class RealClass extends AbstractClass {
RealClass() { } // calls super() implicitly
}
AbstractClass myClass = new RealClass();
Example of your code with calling super() with arguments:
class RealClass extends AbstractClass {
RealClass() {
super(1, 2);
}
}
class AbstractClass {
AbstractClass(int foo, float boo) {}
}
AbstractClass myClass = new RealClass();

SuperClass Constructor Behavior for SubClass Java

I'm reading java docs and reading about Constructors I got confused about the below paragraph.
You don't have to provide any constructors for your class, but you
must be careful when doing this. The compiler automatically provides a
no-argument, default constructor for any class without constructors.
This default constructor will call the no-argument constructor of the
superclass. In this situation, the compiler will complain if the
superclass doesn't have a no-argument constructor so you must verify
that it does. If your class has no explicit superclass, then it has an
implicit superclass of Object, which does have a no-argument
constructor.
What does mean that the compiler will complain if the superclass doesn't have a no-argument constructor
Reference: Java Docs
https://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html
Let's imagine a Base class such as
public class Base {
public Base(String s) {
}
}
Let's now create a subclass:
public class Sub extends Base {
}
That won't compile, because the above code is equivalent to
public class Sub extends Base {
// added by compiler because there is no explicitely defined constructor in Sub
public Sub() {
}
}
which is equivalent to
public class Sub extends Base {
// added by compiler because there is no explicitely defined constructor in Sub
public Sub() {
// added by compiler if there is no explicit call to super()
super();
}
}
The line super()tries to call the no-arg constructor of Base, but there is no such constructor.
The only way to have Sub compile is thus to explicitely define a constructor such as
public class Sub extends Base {
public Sub() {
super("some string");
}
}
By default every class has a no-argument constructor. If you create class A with a constructor with arguments, when class B extends A, you need to explicitly create a constructor which will call the super class constructor with arguments. Basically when you create a constructor, you lose the default call to the no-arg constructor (unless the constructor you created is still a no-arg constructor.
A constructor of the superclass and the subclass has to be called, implicitly or explicitly. Always.
If you provide a constructor for the subclass yourself, you can choose, which superclass constructor to call.
But if you don't provide a constructor for your subclass, Java creates a no-argument constructor for you. In that constructor it has to call a superclass constructor. But if there is no no-argument constructor in the superclass, Java cannot know which superclass constructor to call and which argument to use to do so.
class Superclass {
Superclass(String argument) {
//...
}
}
class Subclass extends Superclass {
// Implicit no-argument constructor, created by Java
Subclass() {
super(/* what String can Java put here? it cannot know it */);
}
}
Now, if there is a no-argument constructor of Superclass, Java can just call super(); in the default Subclass constructor.
Btw. that also happens automatically, if you define the Subclass constructor yourself and don't add an explicit call to a Superclass constructor. The Subclass constructor always calls a Supeclass constructor, be it explicitly or implicitly.

How is this subclass implicitly calling the constructor of its parent class?

I have these two classes:
public class Document {
private static int quantity = 0;
public Document() {
quantity = quantity + 1;
}
public static int getQuantity() {
return quantity;
}
}
public class Book extends Document {
private int numChapters;
public Book(int numChapters) {
this.numChapters = numChapters;
}
public static void main(String[] args) {
Book b1 = new Book(4);
Book b2 = new Book(6);
Document d1 = new Document();
System.out.println(Document.getQuantity());
}
}
The program here returns 3, but I expect it to return 1. Can someone tell me what is happening in the code? It seems that the parent class's constructor is being implicitly called when b1 and b2 are created. From what I understand, subclasses don't inherit the constructor of their parent class.
See the docs:
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.
You have a no-argument constructor which is automatically called.
This behavior makes sense, constructors are meant to create objects. So it should contain proper initialization code for its class. What if you your class extends another one? Shouldn't it contain all the code needed to construct that object?
sub-classes must call a constructor of their super class, even if the sub-class's constructors don't explicitly call super(). In fact, if the compiler can't find a super-class's constructor that it can call from the sub-class's constructor, the code won't compile.
It seems that the parent class's constructor is being implicitly called when b1 and b2 are created.
That is correct.
From what I understand, subclasses don't inherit the constructor of their parent class.
That is also correct. However, it does NOT mean that the superclass constructor is not called.
In Java, when an object is created1 using new (or the reflective equivalent) a superclass constructor is always called, whether or not you have a super(...) call in the subclass constructor.
1 - For the record, when an instance is created by object deserialization, no constructors are called. The recreation of the object is done by some behind-the-curtains black magic that makes the object without calling its constructor.

regarding constructors

i was developing the below code....
class P {
//public P(){}
public P(int i) {
}
}
class D extends P {
public D(){ // default constructor must be defined in super class
}
}
public class agf {
public static void main(String[] args) {
}
}
Now in class p explicit parametrized constructor is defined and in class D default constructor is defined but it is still showing the compile time error ,please explain
Your parent Class P explicitly defines a constructor, due to which no-arg constructor will not be added automatically. When you write a no-arg constructor for class D without having a specific constructor call for the class P using super keyword as mentioned below,
Class D extends P {
public D() {
super(10);
}
}
you are instructing it to call the no-arg constructor of P. Since P only has constructor that you defined, it cannot call the no-arg constructor of P.
In simple terms every object of D will have part of P. But it has no idea how to initialize / construct that P part, since it has no no-arg constructor.
In the subclass, if you don't invoke a superclass constructor explicitly, there must be a default superclass constructor that the VM can invoke for you.
In the superclass, if you explicitly define a constructor, the default no-argument constructor is NOT generated by the compiler.
Therefore, in the situation you show, you defined a non-default constructor in the superclass, which prevented the compiler from generating the default no-arg constructor. Then in the subclass, you didn't explicitly invoke a constructor in the superclass. The compiler tried to generate a no-arg superclass constructor call and didn't find a suitable constructor to call.
Inside this constructor:
public D()
{
// no call to super?? implicit call to super()
}
There is an implicit call to the empty constructor of the super class (which doesn't exist in your case)
Either implement an empty constructor in the super class, or call the parameterized constructor explicitly, e.g.:
public D()
{
super(1);
}
I would suggest you read this tutorial as well.
When creating an instance of class D, the constructor of P is first called (since D is also P). The problem is that P's constructor cannot be called since a value has to be provided to it, and that's something you're not currently doing.
To fix that, the first line in D's constructor have to be super(value), while value can be a parameter sent to D's constructor, or..anything else you want (in case you want to leave D's constructor a default one).
You can go through it step-by-step in debug, it can help to clear things out.

Super() the first thing to do

So I have this code.
public class HourlyWorker extends Worker {
private int hours;
public HourlyWorker(String name, int salRate,int hours) {
super(name, salRate);
this.hours=hours;
}
#Override
void computePay() {
int pay;
if(hours<60)
{
System.out.println("haha");
pay=super.getSalRate()*hours; //CALLING SUPER HERE.
System.out.println("pay of"+super.getName()+"="+pay);
}
}
}
Now in the Worker class, I have this method getSalRate.
I was told that super shall be the first line of code in a method. But if I am here calling it in the middle(the expression given); It works just fine.
Can someone tell me, what really do you mean, when someone says that "Make Sure That Super Is The First Line Of Code
Is It just for the constructors?
The enforcement of first calling super() only applies in constructors. Even if it's left out, a call to the default super() constructor is inserted during compilation.
In a constructor, you can optionally call the superclass constructor with super, on the first line of the constructor only. If you don't, the default superclass constructor is called implicitly.
Elsewhere, you can use super anywhere within a method, initializer or constructor to access a superclass member.
It will just initialise the super class (Worker class) with the parameters passed to the HourlyWorker constructor.
It needs to be called at the start of the constructor. Super can be used on any line elsewhere.

Categories

Resources