Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Object instantiation using different Constructors

Recently my teacher was talking about using different constructors to instantiate objects. But I'm really confused about that. For that I wanna understand why the I get the following compile error.

class SuperClass {
    void superClass(){
        System.out.println("superClass");
    }
}

class SubClass extends SuperClass {
    void subClass(){
        System.out.println("subClass");
    }
}

class Call {
    public static void main(String args[]){
        SuperClass s = new SubClass();
        s.superClass();
    }
}

When I compile and run the following code, I get the output

superClass

But when I try to call subClass() via the s Object, I get the following error.

damn.java:17: cannot find symbol
symbol  : method subClass()
location: class SuperClass
                s.subClass();
                 ^
1 error

OK so, according to this, I can assume that the even I instantiate object with a different constructor, only the Object type specified is loaded to the RAM.

But, when I use the override here like this,

class SuperClass {
    void superClass(){
        System.out.println("superClass");
    }
}

class SubClass extends SuperClass {
    void superClass(){
        System.out.println("subClass");
    }
}

class Call {
    public static void main(String args[]){
        SuperClass s = new SubClass();
        s.superClass();
    }
}

I get the method in the sub class called. Which makes me really confused about this. Anyone can please explain me what happens here when I use a different constructor to instantiate an Object.

like image 737
Shamal Sandeep Avatar asked May 19 '15 08:05

Shamal Sandeep


People also ask

Can you have multiple constructors for an object?

The technique of having two (or more) constructors in a class is known as constructor overloading. A class can have multiple constructors that differ in the number and/or type of their parameters. It's not, however, possible to have two constructors with the exact same parameters.

How do you instantiate an object in a constructor?

Instantiating a ClassThe new operator requires a single, postfix argument: a call to a constructor. The name of the constructor provides the name of the class to instantiate. The constructor initializes the new object. The new operator returns a reference to the object it created.

Can you have 2 constructor with different names?

No. It is not possible. It might be helpful if you explain what it is you're trying to achieve that makes constructors with different names seem like a desirable solution. What is it you're trying to do with your code?

Can a class have 2 constructors in Python?

Providing Multiple Constructors With @classmethod in Python. A powerful technique for providing multiple constructors in Python is to use @classmethod . This decorator allows you to turn a regular method into a class method. Unlike regular methods, class methods don't take the current instance, self , as an argument.


3 Answers

At runtime the JVM knows that your s variable is a "SubClass" and thus can call the right (overwritten) method.

The problem you're having is at compile time though. The compiler tries to verify your program to make sure that you didn't make any mistakes. It has no idea about the types of variables except the type you're telling it about.

// the Java compiler remembers that there is a variable called 's' and that
// it has the type 'SuperClass'. Note that the compiler does not check the
// actual type of the instance. It just checks to see if the assignment is
// is valid. Since the right side is of type 'SubClass' and the left side
// has the type 'SuperClass' which is a parent of 'SubClass' this assignment
// is valid for the compiler. But it ONLY remembers that 's' is of type
// 'SuperClass' since that is what you told it about 's'.
SuperClass s = new SubClass();

// Here the compiler sees 's' and looks up its type. The type of 's' is
// 'SuperClass' as remembered earlier. javac will no go and look up the
// definition of 'SuperClass' and finds out that 'SuperClass' does not
// have a method with the name 'subClass' so you get a compiler error.
s.subClass();

The reason that the compiler does this is, that you told the compiler 's' is of SuperClass type. So, any assignment of anything that extends SuperClass is a valid assignment for 's'. Theoretically you could assign a SuperClass to 's'. If the compiler would not perform this check you would be able to write code that calls methods on objects that might not have those methods, which would lead to a runtime error. Having an error like that randomly come up during runtime is much worse than the compiler just checking all the assignments and calls since you can fix those immediately and the runtime errors are sometimes hard to find and fix.

As others have pointed out you can tell the compiler about your 's' actually being a 'SubClass' later on by casting it:

((SubClass) s).subClass();

With this you basically tell the compiler: "I know that s is actually a 'SubClass', so please treat it like one for this part". If you're somehow wrong about that though and your 's' is actually a 'SuperClass' during runtime you will get a 'ClassCastException' which is a runtime error, since the JVM does not know what to do at this point.

like image 53
mhlz Avatar answered Oct 17 '22 08:10

mhlz


First of all, you are not asking about different constructors of the same class. You are asking about different constructors of different classes - SubClass and SuperClass.

Second of all, what you do in the second snippet is called overriding, not overloading.

In Java there's a difference between the compile time type of a variable and the runtime type of that variable.

Here :

SuperClass s = new SubClass();

The compile time type is SuperClass but the runtime type is SubClass. You are only allowed to call methods declared in the compile time type. However, if the runtime type overrides a method that exists in the compile time class, the runtime class's method will be called at runtime.

like image 30
Eran Avatar answered Oct 17 '22 07:10

Eran


You have declared your instance as an instance of SuperClass, so it will behave as such.

If you want to call subClass, there are two options:

  1. ((SubClass)s).subClass();
  2. Declare it as a SubClass: SubClass s = new SubClass();

Either way, you need to inform the JVM that you want it to work with the behavior of a SubClass, not a SuperClass.

like image 3
Stultuske Avatar answered Oct 17 '22 07:10

Stultuske