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.
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.
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.
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?
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.
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.
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.
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:
((SubClass)s).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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With