When a class extends a class, we can use Super-class reference while assigning memory to the subclass object.
I have understood so far is that it is ok to do so, because a subclass inherits the data of its parent class, but it cannot access the members of the subclass because it is the just the reference, and hence does not know of what additions are done by the child class.
My question is when I included method hiding to the above concept, the superclass reference variable started to refer to the child's class function. Why is that ? Why it didnt call it's own method as it is supposed to ?
class A{
void show(){ System.out.print("CLass A. \n"); }
}
class B extends A{
void show(){System.out.print("Class B. \n"); }
}
class Main{
public static void main(String[] args){
A a= new A();
B b= new B();
a.show(); // prints Class A
b.show(); // prints Class B
A a1= new B();
a1.show(); // print Class B. why is this ? it should be Class A as per theory?
}
}
variables and methods are two different things. Variables stick to their types where as methods get executed run time based on the implementation type provided.
Polymorphism. Methods bind dynamically and choosen at run time. If you ovveride them implementation class, they get executed otherwise the implementation from type class gets execute.
When you write
A a1= new B();
Means that please call the implementations from the class B(which is on right side) which are from type A
You have to know about overriding concept in java.
From oracle documentation page regarding overriding:
Overriding and Hiding Methods
Instance Methods
An instance method in a subclass with the same signature (name, plus the number and the type of its parameters) and return type as an instance method in the superclass overrides the superclass's method
The ability of a subclass to override a method allows a class to inherit from a superclass whose behavior is "close enough" and then to modify behavior as needed.
But overriding is different from hiding.
Static Methods
If a subclass defines a static method with the same signature as a static method in the superclass, then the method in the subclass hides the one in the superclass.
The distinction between hiding a static method and overriding an instance method has important implications:
The version of the overridden instance method that gets invoked is the one in the subclass.
The version of the hidden static method that gets invoked depends on whether it is invoked from the superclass or the subclass.
Example to understand:
public class Animal {
public static void testClassMethod() {
System.out.println("The static method in Animal");
}
public void testInstanceMethod() {
System.out.println("The instance method in Animal");
}
}
public class Cat extends Animal {
public static void testClassMethod() {
System.out.println("The static method in Cat");
}
public void testInstanceMethod() {
System.out.println("The instance method in Cat");
}
public static void main(String[] args) {
Cat myCat = new Cat();
Animal myAnimal = myCat;
Animal.testClassMethod();
myAnimal.testInstanceMethod();
}
}
output:
The static method in Animal
The instance method in Cat
It allways calls the method from the most specific class.
Related
class Bank{
float getRateOfInterest(){return 0;}
}
class SBI extends Bank{
float getRateOfInterest(){return 8.4f;}
}
class TestPolymorphism{
public static void main(String args[]){
Bank a = new SBI();
SBI b = new SBI();
a.getRateOfInterest();
b.getRateOfInterest();
}
}
a.getRateOfInterest() and b.getRateOfInterest() both gives same output. So what is the difference between both the statements?
I think 1st is upcasting.
Java methods are all virtual, so the method called depends on the run-time type of the called object, not on the compile-time type of the variable holding the reference.
It's not, if you construct it with new SBI(). It'll always return 8.4f.
All java method is virtual (by design).
They rely on the implementing classes to provide the method implementations.
Here is more information.
- Can you write virtual functions / methods in Java?
- https://en.wikipedia.org/wiki/Virtual_function
Here is an excerpt from wikipedia :-
public class Animal {
public void eat() {
System.out.println("I eat like a generic Animal.");
}
public static void main(String[] args) {
Animal animal=new Wolf ();
animal.eat(); //print "I eat like a wolf!
}
}
class Wolf extends Animal {
#Override
public void eat() {
System.out.println("I eat like a wolf!");
}
}
Virtual functions are resolved 'late'. If the function in question is
'virtual' in the base class, the most-derived class's implementation
of the function is called according to the actual type of the object
referred to, regardless of the declared type of the pointer or
reference. If it is not 'virtual', the method is resolved 'early' and
the function called is selected according to the declared type of the
pointer or reference.
Virtual functions allow a program to call methods that don't
necessarily even exist at the moment the code is compiled.
In the book Java: The complete reference
// Demonstrate when constructors are called.
// Create a super class.
class A {
A() {
System.out.println("Inside A's constructor.");
}
}
// Create a subclass by extending class A.
class B extends A {
B() {
System.out.println("Inside B's constructor.");
}
}
// Create another subclass by extending B.
class C extends B {
C() {
System.out.println("Inside C's constructor.");
}
}
class CallingCons {
public static void main(String args[]) {
C c = new C();
}
}
Output:
Inside A’s constructor
Inside B’s constructor
Inside C’s constructor
It is demonstrating how the constructor of a subclass is called. But why are constructors of the super class called in the absence of a super() constructor.
Why did the Java Language designers consider it necessary to do so?
As others have pointed out, if you don't start your constructor with a super(...) call, the compiler will put in a call to super() for you.
As to the why, you have to start with remembering what a constructor is for in the first place: initializing the object. What does that mean, specifically? In practice, it means assigning values to the object's fields, and establishing invariants.
Without a call to super(), the B and A classes wouldn't have a chance to do that for whatever fields they contain. And you can't even have the C() constructor do it for them, if those fields are private, since private fields aren't accessible outside your class (not even your super class's fields are accessible). Even if you could, it wouldn't be a good idea; it would also break encapsulation. For instance, imagine having to change your code if a super class -- possibly a complex one whose internals you're not an expert in -- suddenly decided to change its implementation details.
To illustrate this, consider a very simple set of classes:
public class Super {
private final String name;
Super() {
name = "default";
}
public String name() {
return name.toUpperCase();
}
}
public class Sub extends Super {
public Sub() {
// don't do anything
}
}
When you instantiate Sub, it will start out by calling Super's constructor. If it didn't, the name field would be null (the default value for reference types). But the name() method doesn't check for null; it assumes that the reference is non-null, because the constructor establishes that invariant. So, in our pseudo-Java that doesn't call the super constructor, Super.name has to get a bit more complicated -- it has to check for name == null.
You can imagine that as the classes gain more fields, with more interesting invariants, this toy example can become more and more complicated. Forcing you to call the super constructor -- either explicitly or implicitly -- lets the authors of that super class establish their invariants, resulting in simpler, more maintainable code.
Every constructor calls its superclass constructor. super() call take place as the first line in the constructor. From javadoc:
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.
more here
Because it says so in the Java Language Specification.
If a constructor body does not begin with an explicit constructor invocation and the constructor being declared is not part of the primordial class Object, then the constructor body implicitly begins with a superclass constructor invocation "super();", an invocation of the constructor of its direct superclass that takes no arguments.
Even it has a role with Abstract classes also. we can't initialize object of abstract class. But Child class of Abstract class calls the super() method by default. So abstract class constructor can initialize its instance variables.
for example:
public abstract class TestA {
private int a;
public TestA()
{
a=10;
}
public int displayA()
{
return a;
}
abstract void display();
}
public class TestB extends TestA{
#Override
void display() {
System.out.println("this is class B");
}
}
package Abstract;
public class TestMain {
public static void main(String[] args) {
TestA obj= new TestB();
System.out.println(obj.displayA());
}
}
Output is : 10
Here you can see, when we initiating object of class TestB , by default super constructor is calling and TestA's constructor is assigning the value of a. If super will not be called by default we can't assign instance variables of abstract class.
Inheritance is basically inheriting all the properties of your parent class. So if a sub class constructor is called, it should definitely and by default inherit all its parent class properties also. In the following code, all the properties of class A should be made available in class B also, so if I just call B's constructor, all the class A's properties(except private) are also initialized and made available, meaning B has inherited A's properties
class A {
protected int a;
A() {
a=12;
System.out.println("Inside A's constructor.");
}
}
class B extends A {
B() {
System.out.println("Inside B's constructor.");
System.out.println(a);
}
}
public class ConstructorInheritance {
public static void main(String args[]) {
B b=new B();
}
}
output:
Inside A's constructor.
Inside B's constructor.
12
Imagine class C accessing an unitialized variable of class B or A. Implicitly calling constructors of class B-->class A makes sure that you are always accessing initialized variables of inherited classes(A or B)
"The Java programming language" says "A constructor in subclass can initialize its individual state, however, as keeping contract, only super class knows how to initialize super class's state".
Thus, constructor of super class have to be called. There is sequence how the constructor processed:
Call super class constructor
Initialize fields with initializers and initialization blocks
Execute body of the constructor
For more details, have a look of the book to section "3.2".
public class B extends A{
public static void main(String[] args) {
new B().privateMethod();//no error -output B-privateMethod.Sounds like overriding
new B().staticMethod(); //no error -output B-StaticMethod.Sounds like overriding
}
private void privateMethod() {
System.out.println("B-privateMethod.");
}
static void staticMethod() {
System.out.println("B-StaticMethod.");
}
}
class A{
private void privateMethod() {
System.out.println("A-privateMethod.");
}
static void staticMethod() {
System.out.println("A-StaticMethod.");
}
}
On R&D I found in case of privateMethod()- since this method was not available on object of child class so child class's and parent class's privateMethod() are separate method and they have no relationship so this is not overriding.
but in case of staticMethod()- parent class's method was available on object of child class ,and when we define this in child class, object of child class start pointing to child class method.this looks like method overriding but not,since static method does not override.
how does static method handle by java developement kit?
new B().privateMethod();
this is not overriding, since B doesn't see A's privateMethod().
new B().staticMethod();
this is not overriding, calling a static method via an instance is allowed, though it can be confusing. It is exactly the same as calling it via the class name - B.staticMethod(). If a super class A of B has a static method visible from B, you can call that method from B (and it doesn't matter if you write B.staticMethod() or A.staticMethod() or new B().staticMethod().
If later you define a static method of the same name in B, that method hides the method of the same name in A, so calling B.staticMethod() or new B().staticMethod() now invokes B's static method. However, calling A.staticMethod() will still invoke A's static method.
Polymorphism is not for static methods. Static methods are called with JVM instructions invokestatic, whereas polymorphism is achieved with invokevirtual. The calls to static methods are determined at compile time, and polymorphic methods are dynamically dispatched at runtime.
You can easily tweak your code so that A.staticMethod() is called, by just assigning new B() to a variable of type A.
public static void main(String[] args) {
new B().privateMethod();
A b = new B(); // change here.
b.staticMethod(); // A.staticMethod() is called here.
}
Never speak about static and override in the same sentence.
The whole concept of overridable methods is to dynamically bind at runtime which method is to be executed. Consider this:
class A { void print() { out.println("A"); }
class B extends A { void print() { out.println("B"); }
A obj = new B();
obj.print();
Although the variable obj is of type A, it still prints out "B".
Static methods on the other hand are bound at compile time. This means the compiler uses the type of the variable (or the expression) to determine what method to execute:
class A { static void print() { out.println("A"); }
class B extends A { static void print() { out.println("B"); }
A obj = new B();
obj.print();
This now yields "A". Unfortunately the Java language allows to call static methods on variables or expressions. This is not recommended! Better call static methods on the type itself:
A.print();
B.print();
In the first example - obj.print(); - the compiler automatically translates the statement into A.print(). The actual object does not count. In fact you could write the following:
A obj = null;
obj.print();
Or:
((A) null).print();
That still prints "A".
The following code in java, when run on elipse, gives same output even if we replace
superclass s=new sub();
with,
sub s= new sub();
Note that we have overridden methods.
Output is:
changed supermethod in sub class
num is sub class 5
Code:
public class superclass {
int num=2;
public static void main(String str[]){
superclass s=new sub();
//HERE: nothing changes if we write, sub s=new sub();
s.supermethod();
s.method();
}
void supermethod(){
System.out.println("supermethod as in superclass");
}
void method(){
System.out.println("num in superclass "+num);
}
}
class sub extends superclass{
int num=5;
void method(){
System.out.println("num is sub class "+num);
}
void supermethod(){
System.out.println("changed supermethod in sub class");
}
}
Please point out, what are the differences in creating a sub class object in these two ways. And will there be any difference in accessing methods and variables?
(our java teacher says, accessing method and variables will be different in both cases)
Also, what happens to the static methods, like main. Tough i know it is inheritable, but can someone highlight its behavior in sub classes?
In Java, all non-static methods are "virtual", meaning that they are based on the runtime type of the underlying object rather than the type of the reference that points to that object. Therefore, it doesn't matter which type you use in the declaration of the object, the behavior will be the same.
What the declaration does affect, is the methods that are visible at compile-time. If SubClass has a method that SuperClass does not (let's call it subMethod()), and you construct your object as
SuperClass s = new SubClass();
Then you will only be able to call methods on it that are available on SuperClass. That is, attempting to call s.subMethod() will give you a compile time error. But, as you have discovered, if there methods are present in SuperClass, but overridden by SubClass, it will be the overridden method that will be executed.
Static methods, on the other hand, are not virtual. Running the code below
public class StaticTest {
public static void main(String[] args) {
SuperClass s = new SubClass();
s.method(); // bad idea - calling static method via an object reference
}
public static class SuperClass {
public static void method() {
System.out.println("SuperMethod");
}
}
public static class SubClass extends SuperClass {
public static void method() {
System.out.println("SubMethod");
}
}
}
prints out "SuperMethod". You should rarely care, however, that static methods are non-virtual because you should never call them via an object reference as I have done above. You should call them via the class name:
SuperClass.method();
I'm rewriting your code here with some modification.
Please look at the changes.
public class superclass {
int num=2;
public static void main(String str[]){
superclass s=new sub();
//HERE: nothing changes if we write, sub s=new sub();
s.supermethod();
s.method();
}
...
...
//This method is not overridden.
void methodInSuper(){
System.out.prinln("method not overridden.");
}
}
class sub extends superclass{
int num=5;
...
...
//This is only in subclass.
void methodInSub(){
System.out.println("method only in subclass.");
}
}
Now when you are creating an object like this:
superclass s1=new sub();
Then you can call all the overridden methods like
s1.supermethod();
s1.method();
In this case the methods of subclass will be called.
you can also call methods of superclass those are not overridden like
s1.methodInsuper();
but if you try to access method defined only in subclass like
s1.methodInsub();
then it will be a compile time error.
It is becoz s1 is of type Superclass.
If you still want to call the method in subclass then you need to typecast s1 to subclass like
Sub s = (Sub) s1;
After that you can call the method of the subclass.
And if you create an object like
Sub s2 = new Sub();
Then you can access any methods defined in subclass or superclass.
The earlier creation of object is basically used for implementing "Run Time Ploymorphism".
Hope you got your answer.
you are creating Object of sub and assigning it to super's reference.if you dont
1)first case:-
superclass s=new sub();
s.supermethod();
s.method();
in above case methods of sub will be called but these two method should be present in superclass also(if not present then compile time error)
2)second case:-
sub s=new sub();
s.supermethod();
s.method();
in this also methods of sub will be ,these method may or may not be present super.
let's take an example:
sup is a reference variable for a class A's objects. and sub is a reference variable for a class B's objects. let's suppose B extends A . so if we write "sup = sub;" or "sup = new B();" this statement enables us to get the attributes that are common between the 2 classes . i.e : the attributes that were inherited by B ... we use this trick to check for attributes inherited by B and were changed.
I'm confused about what it means to cast objects in Java.
Say you have...
Superclass variable = new Subclass object();
(Superclass variable).method();
What is happening here? Does the variable type change, or is it the object within the variable that changes? Very confused.
Have a look at this sample:
public class A {
//statements
}
public class B extends A {
public void foo() { }
}
A a=new B();
//To execute **foo()** method.
((B)a).foo();
Say you have a superclass Fruit and the subclass Banana and you have a method addBananaToBasket()
The method will not accept grapes for example so you want to make sure that you're adding a banana to the basket.
So:
Fruit myFruit = new Banana();
((Banana)myFruit).addBananaToBasket(); ⇐ This is called casting
The example you are referring to is called Upcasting in java.
It creates a subclass object with a super class variable pointing to it.
The variable does not change, it is still the variable of the super class but it is pointing to the object of subclass.
For example lets say you have two classes Machine and Camera ; Camera is a subclass of Machine
class Machine{
public void start(){
System.out.println("Machine Started");
}
}
class Camera extends Machine{
public void start(){
System.out.println("Camera Started");
}
public void snap(){
System.out.println("Photo taken");
}
}
Machine machine1 = new Camera();
machine1.start();
If you execute the above statements it will create an instance of Camera class with a reference of Machine class pointing to it.So, now the output will be "Camera Started"
The variable is still a reference of Machine class. If you attempt machine1.snap(); the code will not compile
The takeaway here is all Cameras are Machines since Camera is a subclass of Machine but all Machines are not Cameras. So you can create an object of subclass and point it to a super class refrence but you cannot ask the super class reference to do all the functions of a subclass object( In our example machine1.snap() wont compile). The superclass reference has access to only the functions known to the superclass (In our example machine1.start()). You can not ask a machine reference to take a snap. :)
Sometimes you will like to receive as argument a Parent reference and inside you probably want to do something specific of a child.
abstract class Animal{
public abstract void move();
}
class Shark extends Animal{
public void move(){
swim();
}
public void swim(){}
public void bite(){}
}
class Dog extends Animal{
public void move(){
run();
}
public void run(){}
public void bark(){}
}
...
void somethingSpecific(Animal animal){
// Here you don't know and may don't care which animal enters
animal.move(); // You can call parent methods but you can't call bark or bite.
if(animal instanceof Shark){
Shark shark = (Shark)animal;
shark.bite(); // Now you can call bite!
}
//doSomethingSharky(animal); // You cannot call this method.
}
...
In above's method you can pass either Shark or Dog, but what if you have something like this:
void doSomethingSharky(Shark shark){
//Here you cannot receive an Animal reference
}
That method can only be called by passing shark references
So if you have an Animal (and it is deeply a Shark) you can call it like this:
Animal animal...
doSomethingSharky((Shark) animal)
Bottom line, you can use Parent references and it is usually better when you don't care about the implementation of the parent and use casting to use the Child as an specific object, it will be exactly the same object, but your reference know it, if you don't cast it, your reference will point to the same object but cannot be sure what kind of Animal would it be, therefore will only allow you to call known methods.
Superclass variable = new subclass object(); This just creates an object of type subclass, but assigns it to the type superclass. All the subclasses' data is created etc, but the variable cannot access the subclasses data/functions. In other words, you cannot call any methods or access data specific to the subclass, you can only access the superclasses stuff.
However, you can cast Superclassvariable to the Subclass and use its methods/data.
Lets say you have Class A as superclass and Class B subclass of A.
public class A {
public void printFromA(){
System.out.println("Inside A");
}
}
public class B extends A {
public void printFromB(){
System.out.println("Inside B");
}
}
public class MainClass {
public static void main(String []args){
A a = new B();
a.printFromA(); //this can be called without typecasting
((B)a).printFromB(); //the method printFromB needs to be typecast
}
}
In this example your superclass variable is telling the subclass object to implement the method of the superclass. This is the case of the java object type casting. Here the method() function is originally the method of the superclass but the superclass variable cannot access the other methods of the subclass object that are not present in the superclass.
For example you have Animal superclass and Cat subclass.Say your subclass has speak(); method.
class Animal{
public void walk(){
}
}
class Cat extends Animal{
#Override
public void walk(){
}
public void speak(){
}
public void main(String args[]){
Animal a=new Cat();
//a.speak(); Compile Error
// If you use speak method for "a" reference variable you should downcast. Like this:
((Cat)a).speak();
}
}
in some cases we can’t provide guarantee for the type of elements or objects present inside our collection or wise,
at the time of retrieval compulsory we should perform type casting otherwise we will get compile time error.
Arrays are always type safe that is we can provide the guarantee for the type of elements present inside array.
to achieve type safety we have to use typecasting.
Casting is necessary to tell that you are calling a child and not a parent method. So it's ever downward. However if the method is already defined in the parent class and overriden in the child class, you don't any cast. Here an example:
class Parent{
void method(){ System.out.print("this is the parent"); }
}
class Child extends Parent{
#override
void method(){ System.out.print("this is the child"); }
}
...
Parent o = new Child();
o.method();
((Child)o).method();
The two method call will both print : "this is the child".