Why can't I extend the "generic method" interface and narrow its type down to my inherited "class generic" interface?

I am showing an example of what I mean, which is simpler. Imagine that the generic type C means Color Type: So for visual simplification, suppose C is C extends color

interface Screen {
   <C> Background<C> render(Plane<C> plane);
}

interface MonochromeScreen<C> extends Screen{
       @Override
       Background<C> render(Plane<C> plane);  
}

This will cause a compilation error with a name error explaining that both have an erase of the same type, but are not valid.

But I cannot understand why we could not just let the signature be redefined if it is more restrictive. I mean, in the end, the only difference is the volume of the generic type, the Screen in the whole method, and in MonochromeScreen in general.

, , , : 20 , child , / ( - ). , sccreen - , , , , , , , .

?

EDIT: Sotirios Delimanolis, , , , , , ,

+2
4

, :

MonochromeScreen<Red> redScreen = ...;
Screen redScreenJustAScreen = redScreen;
Plane<Blue> bluePlane = null;
redScreenJustAScreen.<Blue>render(bluePlane);

, , , , -, ClassCastException, , redScreenJustAScreen, Plane<Red>, Plane<Blue>.

, , , , . , .

, , , .

+4

, .

interface Screen {
   <C> Background<C> render(Plane<C> plane);
}

, render() C.

, :

Screen s = ...;
Background<Red> b1 = s.render(new Plane<Red>());
Background<Blue> b2 = s.render(new Plane<Blue>());

, MonochromeScreen:

interface MonochromeScreen<C> extends Screen{
   Background<C> render(Plane<C> plane);  
}

: C , .

MonochromeScreen<Red> s = ...;
Background<Red>  b1 = s.render(new Plane<Red>());
Background<Blue> b2 = s.render(new Plane<Blue>()); // this won't compile because you declared that s only works with Red type.

, Screen s = new MonochromeScreen<Red>(); , MonochromeScreen Screen.


, . , Color, . ?

interface Plane {
    Color getColor();
}

interface Background {
    Color getColor();
}

interface Screen {
   Background render(Plane plane);
}

. :

class MonochromeScreen implements Screen {
    private final Color color; // this is the only colour we have
    public Background render(Plane plane) {
        if (!plane.getColor().equals(color))
           throw new IllegalArgumentException( "I can't render this colour.");
        return new Background() {...}; 
    }
}

.

: ? , :

public void renderPrimaryPlanes(Screen s) { //this looks like a good method
    s.render(new Plane(Color.RED));
    s.render(new Plane(Color.GREEN));
    s.render(new Plane(Color.BLUE));
}

...
Screen s = new MonochromeScreen(Color.RED);
renderPrimaryPlanes(s); //this would throw an IAE

, . , renderPrimaryPlanes(). . ?

, , , , LSP , . , : , Screen, , , MonochromeScreen, .

+2

, - , , .

, ,

public interface Screen<C> {
    Background<C> render(Plane<C> plane);
}

public interface MonochromeScreen<C> extends Screen<C> {

  Background<C> render(Plane<C> plane);
}

, , , , <C> - , . .

public interface MonochromeScreen<HI> extends Screen<HI> {

  Background<HI> render(Plane<HI> plane);
}

, . C HI - . Screen<C> extends Screen<HI>, java, C - Holder, HI, .

<C> Background<C> render(Plane<C> plane);

, .

MonochromeScreen<String> ms;
ms.render(new Plane<Banana>());

<C> Background<C> render(Plane<C> plane);

Background<Banana> render(Plane<Banana> plane);

Background<C> render(Plane<C> plane);

Background<String> render(Plane<String> plane);

, java .

0

FYI: . , . , , , . (aka Color), .):

Screen.java

public interface Screen {
    public interface Color {}
    public class Red  implements Color {}
    public class Blue implements Color {}

    static Screen getScreen(){
        return new Screen(){};
    }
    default <C extends Color> Background<C> render(Plane<C> plane){
        return new Background<C>(plane.getColor());
    }
}

MonochromeScreen.java

interface MonochromeScreen<C extends Color> extends Screen{

    static <C extends Color> MonochromeScreen<C> getScreen(final Class<C> colorClass){
        return new MonochromeScreen<C>(){
            @Override public Class<C> getColor() { return colorClass; };
        };
    }

    public Class<C> getColor();

    @Override
    @SuppressWarnings("unchecked")
    default Background<C> render(@SuppressWarnings("rawtypes") Plane plane){
        try{
            C planeColor = (C) this.getColor().cast(plane.getColor());
            return new Background<C>(planeColor);
        } catch (ClassCastException e){
            throw new UnsupportedOperationException("Current screen implementation is based in mono color '" 
                                                   + this.getColor().getSimpleName() + "' but was asked to render a '"
                                                   + plane.getColor().getClass().getSimpleName() + "' colored plane" );
        }
    }
}

Plane.java

public class Plane<C extends Color> {   
    private final C color;
    public Plane(C color) {this.color = color;}
    public C getColor()   {return this.color;}
}

Background.java

public class Background<C extends Color> {  
    private final C color;
    public Background(C color) {this.color = color;}
    public C getColor()        {return this.color;}
}

MainTest.java

public class MainTest<C> {

    public static void main(String[] args) {

        Plane<Red> redPlane   = new Plane<>(new Red());
        Plane<Blue> bluePlane = new Plane<>(new Blue());

        Screen coloredScreen = Screen.getScreen();
        MonochromeScreen<Red> redMonoScreen = MonochromeScreen.getScreen(Red.class);
        MonochromeScreen<Color> xMonoScreen = MonochromeScreen.getScreen(Color.class);

        Screen redScreenAsScreen = (Screen) redMonoScreen;

        coloredScreen.render(redPlane);
        coloredScreen.render(bluePlane);
        redMonoScreen.render(redPlane);
        //redMonoScreen.render(bluePlane); --> This throws UnsupportedOperationException*
        redScreenAsScreen.render(redPlane);
        //redScreenAsScreen.render(bluePlane); --> This throws UnsupportedOperationException*
        xMonoScreen.render(new Plane<>(new Color(){})); //--> And still I can define a Monochrome screen as of type Color so  
        System.out.println("Test Finished!");           //still would have a wildcard to make it work as a raw screen (not useful 
                                                        //in my physical model but it is in other abstract models where this problem arises

    } 
}
  • redScreen:

    java.lang.UnsupportedOperationException: the current screen implementation is based on the monochrome color Red, but he was asked to display the blue color Plane

0
source

Source: https://habr.com/ru/post/1619640/


All Articles