Search code examples
javasuperoverridingsubtyping

Java super method call in a subtype overridden method


could someone please explain me why if i run this code the output is [4, 2]:null and not [4,2]: purple? What I understand is that the problem sits in the toString method in the superClass. In fact if I remove the "final" from toString in SuperClass and write a toString method like

    public String toString() {
        return this.makeName();
    } 

in the subClass all works fine. But I don't really understand the concept behind that. Does exists something to read about this?

Thank you for your time.

public class Point { 
    protected final int x, y;
    private final String name;

    public Point(int x, int y) { 
        this.x = x;
        this.y = y;
        name = makeName();
    }
    protected String makeName() { 
        return "["+x+", "+y+"]";
    }
    public final String toString(){ 
        return name;
    } 
}

ColorPoint.java:

public class ColorPoint extends Point { 
    private final String color;

    public ColorPoint(int x,int y, String color) { 
        super(x, y);
        this.color = color;
    }
    protected String makeName() {
        return super.makeName() + ":" + color;
    }
    public static void main(String[] args) { 
        System.out.println(new ColorPoint(4, 2, "purple"));
    } 
}

Solution

  • When you do :

    super(x, y);

    it invokes the constructor of your super class and hence makeName() method (due to line name = makeName();).

    Since you redefined it in your subclass it calls it but color isn't defined at this moment.

    Hence return super.makeName() + ":" + color; is equivalent to return super.makeName() + ":" + null;

    So the execution flow is equivalent in the following (simplified) :

    new ColorPoint(4, 2, "purple") //<-- creating ColorPoint object
    super(x, y); //<-- super call
    this.x = 4; 
    this.y = 2;
    name = makeName(); //<-- call makeName() in your ColorPoint class
    return super.makeName() + ":" + color; //<-- here color isn't defined yet so it's null
    name = "[4, 2]:null";
    color = "purple";
    /***/
    print [4, 2]:null in the console //you call the toString() method, since it returns name you get the following output
    


    Note that you could really simplify your classes with the following :

    class Point { 
        protected final int x, y;
    
        public Point(int x, int y) { 
            this.x = x;
            this.y = y;
        }
    
        @Override
        public String toString() { 
            return "["+x+", "+y+"]";
        }
    }
    
    class ColorPoint extends Point { 
        private final String color;
    
        public ColorPoint(int x,int y, String color) { 
            super(x, y);
            this.color = color;
        }
    
        @Override
        public String toString() {
            return super.toString() + ":" + color;
        }
    }