0

Let's say I have a super-class Ugrad like this:

public class Ugrad{

    int DM = 140;
    int perYear() { return DM/4; }
}

And I have a sub-class of that class named Grad , like this:

public class Grad extends Ugrad{
    int DM = 28;
     int perYear() { return DM/2; };

Now , I have a tester class , in which I do some prints to learn how objects work, like this:

//In the line-comments I denote what the result of the print will be.
public class Tester{
  public void main(String[] args){
     Grad g = new Grad();
     System.out.println(g.DM); // 28
     System.out.println(g.perYear()); // 14
     Ugrad u = (Ugrad) g;
     System.out.println(u.DM); //140
     System.out.println(u.perYear()); //14
  }
}

My question is how does super-class cast works on objects? Why does u.perYear prints 14 equals to g.DM/2 when u.DM equals to 140?

Tolis M.
  • 27
  • 9
  • Since the `DM` attribute is not a constant variable it should be spelled in all lower case per the Java Coding Conventions. – Lew Bloch Oct 31 '19 at 19:06

1 Answers1

2
  1. You are casting a subclass to a superclass. This is upcasting (or implicit casting) as per: Inheritance -> Casting Obects This means that this casting can be done implicitly. You do not have to put casting operator after the assignment. Every Grad object is implicitly an object of class Upgrad because of your declaration: Grad extends Upgrad. I.e. this will work:
Upgrad u = g;
  1. You have overriden the perYear() method. After casting to a superclass and calling this method it will stay as implemented in Grad class because of polymorphism principles and override rules for Java: This questions has in fact been answered here and here on Stackoverflow. To quote Learning Java by Daniel Leuck & Patrick Niemeyer:

    When there are multiple implementations of a method in the inheritance hierarchy of an object, the one in the “most derived” class (the furthest down the hierarchy) always overrides the others, even if we refer to the object through a reference of one of the superclass types.

  2. This is defferent from hiding a field. Hiding or shadowing a field is best described here: Subclassing and inheritance -> Shadowed Variables A different set of types is used there in the link but the meaning is the same:

    Another important point about shadowed variables has to do with how they work when we refer to an object by way of a less derived type (a parent type). For example, we can refer to a DecimalCalculator object as an IntegerCalculator by using it via a variable of type IntegerCalculator. If we do so and then access the variable sum, we get the integer variable, not the decimal one:

    DecimalCalculator dc = new DecimalCalculator();
        

    IntegerCalculator ic = dc;

    int s = ic.sum; // accesses IntegerCalculator sum

    As said in Inheritance -> What You Can Do in a Subclass :

    You can declare a field in the subclass with the same name as the one in the superclass, thus hiding it (not recommended).

Testing code:


class Ugrad {

    int DM = 140;
    int perYear() { return DM/4; }
}

class Grad extends Ugrad {
    int DM = 28; // we have *hidden* Upgrad.DM field by
    int perYear() { return DM/2; }
 }

 public class UpgradGrad {
  public static void main(String[] args){
     Grad g = new Grad();
     System.out.println(g.DM); // Grad.DM field is accessed directly, thus output = 28
     System.out.println(g.perYear()); // 14
     Ugrad u = g; // this will work because of implicit casting to a superclass
     System.out.println(u.DM); // g is casted to u. Grad.DM was hiding Upgrad.DM. Thus Upgrad.DM emerges.
     System.out.println(u.perYear()); // because g is just referred to as Upgrad, its original Grad.perYear() method will be called
  }
}