How to chain methods with subclasses in Java 8

I followed this pattern to implement a chain of methods with subclasses in Java. The goal is that I have a method on a superclass, but you can assign a subclass, for example:

interface Screen {
    <T extends Screen> T setBrightness(int value);
    <T extends Screen> T setContrast(int value);
}

class CrtScreen implements Screen {

    @SuppressWarnings("unchecked")
    @Override
    public <T extends Screen> T setBrightness(int value) {
        // ...
        return (T) this;
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T extends Screen> T setContrast(int value) {
        // ...
        return (T) this;
    }
}

class ColorCrt extends CrtScreen { /* ... */ }

public static void main(String[] args) {
    ColorCrt cc = new ColorCrt().setBrightness(50).setContrast(50);
}

Now I also have container objects to which I want to add my objects, for example:

class Stuff {
    Stuff add(Screen s) {
        // ...
        return this;
    }

    Stuff add(String s) {
        // ...
        return this;
    }

    Stuff add(int i) {
        // ...
        return this;
    }
}

public static void main(String[] args) {
    new Stuff().add(new ColorCrt().setBrightness(50).setContrast(50)).add(25).add("...");
}

Now this no longer works in Java 8, giving me the add (Screen) method is ambiguous for the Stuff type. I understand the reason described here. At the moment, I see only two options:

  • I do not use <T extends, but simply Screen setBrightness(value). I need the ability to assign my implementation class to the appropriate variable, and I must use it when I want to execute the implementation-specific method.

  • . ( ), Java 7.

Java 8, ? , ?

+4
2

:

class CrtScreen implements Screen {

    @SuppressWarnings("unchecked")
    @Override
    public <T extends Screen> T setBrightness(int value) {
        // ...
        return (T) this;
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T extends Screen> T setContrast(int value) {
        // ...
        return (T) this;
    }
}

- setContrast setBrightness , , , ( ). , , , :

interface Screen<T extends Screen> {
    T setBrightness(int value);
    T setContrast(int value);
}

class CrtScreen implements Screen<CrtScreen> {
    @SuppressWarnings("unchecked")
    @Override
    public CrtScreen setBrightness(int value) {
        // ...
        return this;
    }

    @SuppressWarnings("unchecked")
    @Override
    public CrtScreen setContrast(int value) {
        // ...
        return this;
    }
}

-, , (. ):

public static void main(String[] args) {
    new Stuff()
     .add(new ColorCrt().<ColorCrt>setBrightness(50))
     .add(25).add("...");
}
0

, , , interface a abstract class. , Java 8.

:

static abstract class Screen {
    abstract <T extends Screen> T setBrightness(int value);
    abstract <T extends Screen> T setContrast(int value);
}

static class CrtScreen extends Screen {

    @SuppressWarnings("unchecked")
    @Override
    public <T extends Screen> T setBrightness(int value) {
        // ...
        return (T) this;
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T extends Screen> T setContrast(int value) {
        // ...
        return (T) this;
    }
}

static class ColorCrt extends CrtScreen { /* ... */ }

static class Stuff {
    Stuff add(Screen s) {
        return this;
    }

    Stuff add(String s) {
        return this;
    }

    Stuff add(int i) {
        return this;
    }
}

public static void main(String[] args) {
    ColorCrt cc = new ColorCrt().setBrightness(50).setContrast(50);
    new Stuff().add(new ColorCrt().setBrightness(50).setContrast(50)).add(25).add("...");
}
0

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


All Articles