Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Java, what does 'this' indicate in a superclass method called on a subclass that inherits that method?

The code is this:

class Main {  
  public static void main(String args[]) { 
        Person p1 = new Student();
        Person p3 = new Teacher();
        Student p4 = new Student();
        OnlineLecture lec3 = new OnlineLecture();
        
        lec3.addAttendant(p1);
        lec3.addAttendant(p3);
        lec3.addAttendant(p4);
  }
}


abstract class Person {
    public void join(Lecture lec) { 
        System.out.println("Joining "+lec);
    }
    public void join(OnlineLecture lec) {
        System.out.println("Joining "+lec);
    }
}

class Student extends Person {
    public void join(Lecture lec) {
        System.out.println("Student joining "+lec);
    }
}

class Teacher extends Person {
    public void join(OnlineLecture lec) {
        System.out.println("Teacher joining "+lec);
    }
}
    
class Lecture {
    public void addAttendant(Person p) {
        p.join(this);
    }
    public String toString() {
        return "a lecture";
    }
}

class OnlineLecture extends Lecture {
    public String toString() {
        return "an online lecture";
    }
}

I don't understand why the output I get is this:

Student joining an online lecture
Joining an online lecture
Student joining an online lecture

Shouldn't 'join(this)' in the 'addAttendant' method called on lec3 result in a 'join(OnlineLecture lec3)', and therefore give this

Joining an online lecture
Teacher joining an online lecture
Joining an online lecture

as output?

like image 431
MercuryHack Avatar asked Feb 11 '21 16:02

MercuryHack


People also ask

What does a Java subclass inherit from its superclass?

A subclass inherits all the members (fields, methods, and nested classes) from its superclass. Constructors are not members, so they are not inherited by subclasses, but the constructor of the superclass can be invoked from the subclass.

What is superclass and subclass in inheritance?

In Java, it is possible to inherit attributes and methods from one class to another. We group the "inheritance concept" into two categories: subclass (child) - the class that inherits from another class. superclass (parent) - the class being inherited from.

Which keyword is used when a subclass inherits a superclass?

With the use of the extends keyword, the subclasses will be able to inherit all the properties of the superclass except for the private properties of the superclass.

Which key word indicates that a class inherits from another class?

The extends keyword extends a class (indicates that a class is inherited from another class).


2 Answers

Polymorphism & Overloading

Polymorphism

  1. Polymorphism is exhibited when a reference.method() is invoked
  2. This is by nature a dynamic behavior based on the actual object type referenced by the reference
  3. This is where the lookup tables(like vmt in c++) comes into play
  4. Depending on the object pointed by the reference, runtime will decide on the actual method to invoke

Overloading

  1. Method overloading in a compile time decision
  2. The signature of the method is fixed at compile time
  3. There is no runtime lookup needed for any polymorphism exhibited based on the method's parameter types
  4. The parameter is just a parameter for the method in context and it does not care about the polymorphism exhibited by the type

What is happening in the current example?

    static class Lecture {
        public void addAttendant(Person p) {
            p.join(this);
        }
    }
  1. Assuming there is a child class of Lecture overriding addAttendant, then polymorphism can control which method will be called based on the object type when someone invokes a method on a reference type of Lecture or one of its subclass(es).
  2. But, for any call that will eventually land on the Lecture.addAttendant, the method signature that matches the p.join(this) is join(Lecture)(even though p could be dynamically referenced). Here there is no polymorphism even though the object referenced by this could be a polymorphic type.
like image 147
Thiyanesh Avatar answered Oct 19 '22 10:10

Thiyanesh


  • Inside addAttendant method, this inside p.join(this) is hold Lecture class, as there is no implementation of addAttendant in child class. So, it invoke join(Lecture lec) method. It ignores OnlineLecture behaviour.
class Lecture {
    public void addAttendant(Person p) {
        p.join(this);
    }
}

One approach to solving this ambiguous behavior, implement @Override the method addAttendant(Person p) inside OnlineLecture subclass :

public class InheritanceProblem {

    public static void main(String args[]) {
        Person p1 = new Student();
        Person p3 = new Teacher();
        Student p4 = new Student();
        OnlineLecture lec3 = new OnlineLecture();

        lec3.addAttendant(p1);
        lec3.addAttendant(p3);
        lec3.addAttendant(p4);
    }
}

abstract class Person {
    public void join(Lecture lec) {
        System.out.println("Joining " + lec);
    }

    public void join(OnlineLecture lec) {
        System.out.println("Joining " + lec);
    }
}

class Student extends Person {
    public void join(Lecture lec) {
        System.out.println("Student joining " + lec);
    }
}

class Teacher extends Person {
    public void join(OnlineLecture lec) {
        System.out.println("Teacher joining " + lec);
    }
}

class Lecture {
    public void addAttendant(Person p) {
        p.join(this);
    }

    public String toString() {
        return "a lecture";
    }
}

class OnlineLecture extends Lecture {
    @Override
    public void addAttendant(Person p) {
        p.join(this);
    }

    public String toString() {
        return "an online lecture";
    }
}

Output:

Joining an online lecture
Teacher joining an online lecture
Joining an online lecture
like image 1
Md Kawser Habib Avatar answered Oct 19 '22 08:10

Md Kawser Habib