What is the difference between super and this in terms of inheritence? - java

Here is my question, super keyword is used only in case of inheritence ?
In terms of inheritence, what is the difference between this and super?

this refers to the current object, i.e. it's a reference
super refers to the super class, i.e. it's a scoping mechanism
The current object is the same object as the object of the superclass. If you have a Dog that extends Animal, and do new Dog() then you create 1 object, and this object is both the Animal instance and the Dog instance.
Here's an example
class Dog extends Animal {
public void treatWell(DogSpa spa) {
spa.takeCareOf(this); // pass this object to the spa
}
public void makeSound() {
System.out.println("bark");
super.makeSound(); // call makeSound in Animal scope
}
}

this refers to current object, while super refers to current object's parent class.
Consider this:
class Parent {
protected int value;
public void test() {
//print parent
}
}
class Child extends Parent {
public void test() {
//print child
}
private void someMethod() {
this.test();//will print child
super.test();//will print parent
}
}

Related

Java - calling a method by passing child instance to a function with parameter of parent class type [duplicate]

public class Parent {
....
}
public class Child1 extends Parent {
....
public void foo() {
....
}
}
public class Child2 extends Parent {
....
public void foo() {
....
}
}
Here method foo() only exists in the Child classes and CAN NOT be added to the Parent class (not even abstract method). In this situation when I want to call the foo() method on obj which is Parent class's reference then I need to use intanceof with multiple if..else which I want to avoid.
Parent obj = ...// Object of one of the child classes
obj.foo();
EDIT: I Need to use type of obj as Parent only. Else I will not be able to call methods on obj which exists in Parent class.
My Solution: The approach that I am thinking is to define an interface say FooInterface with foo() method and let all the child classes implement it, then I could just type cast the obj to that interface and call foo() method like this:
if(obj instanceof FooInterface){
((FooInterface)obj).foo();
}
Is there a better approach ? Or any improvement to this one?
You can't do it with parent object reference until an unless method is declared in parent class/interface itself.
You have to downcast it to child class because parent class/interface doesn't have any knowledge about the child class other than the contract defined between them.
Here contract means abstract methods.
you can try in this way where there is no need to put a check it.
FooInterface sc =new Child1();
sc.foo();
...
interface FooInterface{
void foo();
}
public class Parent {
}
public class Child1 extends Parent implements FooInterface{
public void foo() {
}
}
public class Child2 extends Parent implements FooInterface{
public void foo() {
}
}
The approach that I am finally taking is to define an interface say FooInterface with foo() method and let all the child classes implement it, then I could just type cast the obj to that interface and call foo() method like this:
Parent obj = ...// Object of one of the child classes
.....
if(obj instanceof FooInterface){
((FooInterface)obj).foo();
}
The polymorphism is applied on object reference, not a type. When you call
FooInterface obj = ...// Object of one of the child classes
obj.foo();
the child class method foo() is called.
If you want to typecast only then there is no need of adding interface. You can typecast it to your desired class and call the method. Example
public class HelloWorld {
public static void main(String args[]) throws FileNotFoundException {
SuperClass sc =new Child1();
if(sc instanceof Child1)//Do same for Child2
((Child1)sc).foo();
}
}
class SuperClass {
}
class Child1 extends SuperClass{
public void foo(){
System.out.println("From child1");
}
}
class Child2 extends SuperClass{
public void foo(){
System.out.println("From child2");
}
}
Output :
From child1
You could implement an AbstractChild inheriting from Parent and then extend this class instead of Parent:
public class Parent {
....
}
public abstract class AbstractChild extends Parent{
public abstract void foo();
}
public class Child1 extends AbstractChild {
....
public void foo() {
....
}
}
public class Child2 extends AbstractChild {
....
public void foo() {
....
}
}
So you need to only check if your instance is instanceof AbstractChild.

How to call default constructor of an abstract class in Java

I tried to research over this topic but could not find a clarity over this. Please help me in this.
In the constructor of a child-class you can call
super(/*params if needed*/);
in order to call its parent's constructor
You can use super() in your child class. You cannot create instance of abstract class(you might know that)
abstract class Parent{
Parent(){
System.out.println("Parent contructor!");
}
}
public class Child extends Parent{
public Child() {
super();
System.out.println("Child contructor!");
}
public static void main(String[] args) {
new Child();
}
}
Even if you do not specify super() in Child class, still the parent class constructor will be called because super() will be put by compiler in default constructor of Child class while generating the .class. If you only have parameterized constructor in Parent class then you will have to explicitly call the parent class constructor by super(..parameter) in your child class constructor . Hope this helps!
Something like this :
abstract class MyClass{
int val;
public MyClass( int val) {
this.val= val;
}
}
class Test extends MyClass{
public Test () {
super(2);
}
}
While you may not call upon a default constructor for an Abastract class, you can invoke the default constructor for the sub-class that embodies your abstract class.
For example:
abstract class Animal {
public Animal (){ ... }
abstract public String sound();
}
class Horse extends Animal{
public Horse(){
super()
}
#Override
public String sound(){
return "neigh";
}
}
class Dog extends Animal{
public Dog(){
super()
}
#Override
public String sound(){
return "woof";
}
}
It is not directly possible to make a new Animal. You can make new Dog-s and Horse-s with annomyously for (common) Type Animal example:
public Animal makeAnimals( Animal existingCreature )
throws InstantiationException, IllegalAccessException
{
return existingCreature.getClass.newInstance();
}
Will make a new instance of the concrete class you provided:
Dog fido = new Dog();
Horse hack = new Horse();
Dog puppy = makeAnimals( fido ); // new uninitialised Dog instance
Horse foal = makeAnimals( hack ); // new uninitialised Horse instance
Alternatively you can make an annomyous instance
Animal parrot = new Animal() {
#Override
public String sound(){
return "squawk";
}
}
As a way to make new animal types. If you were doing something for real like Animals it would probably be better to make a Parot subclass.

How can I copy subclasses by using the parent abstract copy constructor in Java?

I have an abstract class with several subclasses. In the abstract classe I have implemented a copy constructor. Now, I want to clone one of the subclasses using the copy constructor, how can I do this? Obviously I do not know in advance what subclass I have to clone.
Here is an example of what I want to do :
abstract class AbstractClass {
public AbstractClass(AbstractClass ac) {
this();
setX(ac.getX());
setY(ac.getY());
}
// Some setter and getter for X and Y variables
}
class SubclassA extends AbstractClass {
public SubclassA(SubclassA a) {
super(a);
}
}
class SubclassB extends AbstractClass {
public SubclassB(SubclassB b) {
super(b);
}
}
public class Main {
public static void main(String[] args) {
AbstractClass a = new SubclassA();
AbstractClass b = new SubclassB();
// Get a copy of "a" or "b" using the copy constructor of abstract class
AbstractClass newA = AbstractClass(a);
AbstractClass newB = AbstractClass(b);
}
}
There are only two ways I can see to create a copy of a given object without knowing at compile time which class to instantiate (as requested in the question):
Use Reflection to call the copy constructor of the desired class, assuming you know at runtime what the class is, and that said class has a suitable copy constructor.
Call some copy method of the base class which is overridden by subclasses.
The first solution is not good as it requires the use of Reflection. The second can be implemented with the clone()/Cloneable standard mechanism (despite its issues), or with some custom-defined "copy()" method. Your choice.
abstract class AbstractClass {
public AbstractClass(AbstractClass ac) {
this();
setX(ac.getX());
setY(ac.getY());
}
public abstract AbstractClass clone();
// Some setter and getter for X and Y variables
}
class SubclassA extends AbstractClass {
public SubclassA(SubclassA a) {
super(a);
}
#Override
public SubclassA clone() {
return new SubclassA(this);
}
}
class SubclassB extends AbstractClass {
public SubclassB(SubclassB b) {
super(b);
}
#Override
public SubclassB clone() {
return new SubclassB(this);
}
}
public class Main {
public static void main(String[] args) {
AbstractClass a = new SubclassA();
AbstractClass b = new SubclassB();
// Get a copy of "a" or "b" using the copy constructor of abstract class
AbstractClass newA = a.clone(); // is instance of SubclassA
AbstractClass newB = b.clone(); // is instance of SubclassB
}
}
The trick here is to use your own clone method (which has nothing to do with Cloneable what so ever). This method in turns calls the proper copy constructor.
This means you get all the advantages of a copy constructor, and you can be sure that no matter hwta subclass of AbstractClass you get, you always get a copy of the proper subclass without needing to call the constructor yourself.

Understanding the use of Super to access Superclass members

I was referring to the java language specification to understand the use of super. While I understand the first use case i.e.
The form super.Identifier refers to the field named Identifier of the current object, but with the current object viewed as an instance of the superclass of the current class.
I can't seem to understand the following use case:
The form T.super.Identifier refers to the field named Identifier of the lexically enclosing instance corresponding to T, but with that instance viewed as an instance of the superclass of T.
Could someone please explain this with the help of code?
I suppose the following could be illustrative of the second case:
class S{
int x=0;
}
class T extends S{
int x=1;
class C{
int x=2;
void print(){
System.out.println(this.x);
System.out.println(T.this.x);
System.out.println(T.super.x);
}
}
public static void main(String args[]){
T t=new T();
C c=t.new C();
c.print();
}
}
output:
2
1
0
I believe it applies to this situation
public class Main {
static class Child extends Parent{
class DeeplyNested {
public void method() {
Child.super.overriden();
}
}
public void overriden() {
System.out.println("child");
}
}
static class Parent {
public void overriden() {
System.out.println("parent");
}
}
public static void main(String args[]) {
Child child = new Child();
DeeplyNested deep = child.new DeeplyNested();
deep.method();
}
}
In the JLS
The form T.super.Identifier refers to the field named Identifier of
the lexically enclosing instance corresponding to T, but with that
instance viewed as an instance of the superclass of T.
Identifier is overriden, the method.
Here, the lexically enclosing instance is of type Child and its superclass is Parent. So T.super refers to the instance of Child viewed as Parent.
The code above prints
parent

Derived Constructor

In the following code:
import java.io.*;
public class MyClass1
{
MyClass1()
{
System.out.println("base class");
}
public void print()
{
System.out.println("base print");
}
}
class ChildClass extends MyClass1
{
public ChildClass()
{
System.out.println("child class");
}
public void print()
{
System.out.println("child print");
}
}
Why is it that when I create an instance of type ChildClass the constructor of the base class is also executed??
Because your child class extends the base class - it's an instance of the base class and has all of the same fields and variables, etc. Thus the base class must also be instantiated.
For a concrete example, imagine your base class had the following in:
public class Base
{
final private int id;
public Base()
{
this(-1);
}
public Base(int id)
{
this.id = id;
}
public getId()
{
return id;
}
}
A final variable is guaranteed to be instantiated when the class is constructed. Your child class will have an id field (even if it cannot access it directly with child methods), and since this field is private you cannot possible instantiate it with the child constructor - so a base class constructor must be called.
Bear in mind that this isn't solely an issue with final variables, nor is it unique to any particular features you may use - since your child class is a base class, it needs to be properly instantiated as one.
Because that's what's supposed to happen :-)
Your derived class uses the base class as a foundation. In OO speak it is-a base class. That base class also needs to initialise itself, and consequently its constructor must be called.
It's not obvious from your example, but it will make more sense if you give your base class some (protected) members. Initialise them in the base constructor, and consequently they will have the expected values when viewed from your derived class upon construction.
See below. The field value is visible in the child class. What would you expect as the initialised value ?
public class MyClass1
{
protected int value;
MyClass1()
{
System.out.println("base class");
this.value = 42;
}
}
class ChildClass extends MyClass1
{
public ChildClass()
{
// what would you expect 'value' to be here ?
System.out.println("child class " + value);
}
}
Because compiler by default add super() constructor in the child class constructor if it is not specified . Every Constructor Should have either this() in case of without inheritance or super() method when ever there is an inheritance . To illustrate it i have taken this example .
public class Vehicle {
protected int wheels;
protected int lights;
Vehicle(){
System.out.println("Vehicle Class Constructor");
this.wheels=4;
this.lights=2;
}
}
Vehicle is the parent class
class Car extends Vehicle {
public Car(){
#Compiler add the super() constructor by default
System.out.println("Car class constructor");
}
}
Car is the Child class
public class TestCar {
public static void main(String args[]){
Car c = new Car();
System.out.println("Wheels" + c.wheels);
System.out.println("Lights" + c.lights);
}
}
In above code snippet When i compile the TestCar.java file during the Compile time the compiler looks for the Car constructor and checks whether Car class has any parent as soon as it checks that Car class extends the parent class Vehicle , it checks whether user had provided super() in inheritance tree . if not it adds one .
Hope this helps !

Categories