V
V
Vadim2022-03-26 12:46:24
Java
Vadim, 2022-03-26 12:46:24

Covariance of return types in Java, did I understand the essence correctly?

I'm reading the book "Java Philosophy" by Bruce Eckel and got to a small section on return type covariance in Java. I can't figure out if I understood the idea correctly? Code example :

package com.company;

public class Main {
    public static void main(String[] args) {
        Shape s;
        s = new BuildCircle().build();
        System.out.println(s);
        s.methodShape(); 
    }
}

class Shape {
    public String toString() {
        return "Shape";
    }
    public void drawShape(){
        System.out.println("draw Shape");
    }
}

class Circle extends Shape {
    public String toString() {
        return "Circle";
    }
    public void drawShape(){
        System.out.println("draw Circle");
    }
}

class BuildShape {
    Shape build() {
        return new Shape();
    }
    public void BuildingShape(){
        System.out.println("Building Shape");
    }
}

class BuildCircle {
    Circle build() {
        return new Circle();
    }
    public void BuildingCircle(){
        System.out.println("Builiding Circle");
    }
}

output:
Circle
draw Circle

As I understand it, at the output we get a shape object converted to a circle (a more "specialized" object).
As a result, all its methods were redefined to those that are in the Circle class, but the object did not receive new methods, it only redefined its own methods to those that are in the derived class
. Some kind of underinheritance in the opposite direction comes out.
Did I understand correctly what the essence of covariance is? If not, tell me a resource (it is possible in English) where you can read about this in more detail. Thanks in advance

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
Mercury13, 2022-03-26
@zaorduu

The covariance starts when we do . (It’s better to write BuildShape as an interface rather than a class, but the joke is on it.) Covariance is related to the Liskov substitution principle: in order for the child to fit into the contract established by the ancestor, it can tighten the requirements on itself (say, issue a narrower type) and weaken requirements for others (say, to accept a real-time stream like a console / socket - and not just a file that knows its own length and allows rewinding). This “produce a narrower type than the ancestor believes” is covariance. The reverse - to accept a real-time stream, and not just a file - is called contravariance. As far as I know, Java does not have it at the language level, but some parts are managed to be done through templates. class BuildCircle extends BuildShape

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question