2

So I have the following two cases:

Case 1:

public class Person {
   private String name = "Person";
   private String getName() {
      return name;
   }

   public void printName() {
      System.out.println( getName() );
   }
}

public class Student extends Person {
   private double gpa = 0;
   private String getName() {
      return “Student”;
   }
}

public class Driver {
   public static void main(String[] args){
      Person p = new Person();
      Student s = new Student();

      p.printName();  // “Person”
      s.printName();  // “Person”
   }
}

Case 2:

public class Person {
   private String name = "Person";
   public String getName() {
      return name;
   }

   public void printName() {
      System.out.println( getName() );
   }
}

public class Student extends Person {
   private double gpa = 0;
   public String getName() {
      return “Student”;
   }
}

public class Driver {
   public static void main(String[] args){
      Person p = new Person();
      Student s = new Student();

      p.printName();  // “Person”
      s.printName();  // “Student”
   }
}

Case 2 makes the most sense (it's intended behavior).

But why does Case 1 not output the same as Case 2 ("Person" instead of "Student")?

From what I understand, non-static calls implicitly use this. And from this SO post, this and super don't "stick". Thus, for the first case, getName() should use Student's implementation as this refers to the Student instance (regardless of access modifiers). But that doesn't appear to be the case..

Thanks in advance!

2 Answers2

2

For Case 1, Student#getName does not override Person#getName, as the methods are private, meaning they are not accessible to other classes. Because Student#getName implicitly overrides Person#getName (since both are now public), Student is printed in Case 2.

Jacob G.
  • 28,856
  • 5
  • 62
  • 116
  • 1
    I'm trying to learn Java too. Could these also be set to protected and still work? – Dan Zuzevich Nov 06 '17 at 00:36
  • 2
    @DanielZuzevich Absolutely! As long as the child class is able to override the method from its parent, then the child will call its `getName`. – Jacob G. Nov 06 '17 at 00:37
  • 1
    It's helpful to note that `public` object methods in Java are also [`virtual`](https://en.wikipedia.org/wiki/Virtual_function). Hence why case 2 works the way it does; this isn't the case in C++/C# which require the `virtual` keyword on `Person`'s `getName` to work this way. – Powerlord Nov 06 '17 at 01:22
0

In each case Person.printName() calls getName().

In Case 1, the only visible version is Person.getName(), hence that is called for both Person and Student.

In Case 2, Student.getName() overrides Person.getName(), hence the former is called.

So the different visibility applied to getName() influences the outcome. When it's public (or protected), it can be over-ridden and the method called will depend on the object. When it's private, there is no over-riding and Person.getName() is always called.

dave
  • 11,641
  • 5
  • 47
  • 65