Краткий способ создания «вариантов» классов при сохранении иерархии классов в Java? - PullRequest
0 голосов
/ 19 февраля 2019

Скажем, у меня есть эти классы:

interface X {
    public void setX(int x);
    public int getX();
    public void say();
}

interface Y extends X {
    public void shout();
}

class BaseX implements X {
    private int x;
    public BaseX(int x) {setX(x);}

    public void setX(int x) {this.x = x;}
    public int getX() {return x}

    public void say() {
        System.out.println(getX());
    }
}

class BaseY extends BaseX implements Y {
    private int y;
    public BaseY(int x) {super(x); setY(0);}
    public BaseY(int x, int y) {super(x); setY(y);}


    public void shout() {
        System.out.println(y + "!!");
    }
}

Я хочу расширить BaseX и BaseY новыми классами: MyX и MyY:

class MyX extends BaseX {
    public MyX(int x) {super(x);}

    @Override
    public void say() {super.say(); System.out.println("(MyX)");}
    public void printValue(int z) {
        System.out.println("value: " + z + " - x: " + getX());
    }
}

Но вот проблема.Что дальше?Я продляю MyX или BaseY?В этом случае кажется, что мне нужно расширить оба:

class MyY extends MyX, BaseY {
    // impossible. how to do this?
    public MyY(int x) { (MyX super)(x);}
    public MyY(int x, int y) { (BaseY super)(x, y);}

    @Override
    public void say() {(MyX super).say(); System.out.println("(MyY)");}
    @Override
    public void printValue(int z) {(MyX super).printValue(z); System.out.println("(MyY)");}
}

Тогда я бы использовал MyX и MyY примерно так:

MyX mX = new MyX(1);
MyY mY = new MyY(2, 3);

assert mY instanceof MyX; // MyY is a subclass of MyX, so this works.
assert mX instanceof X; // BaseX implements `X`.
assert mY instanceof X; // ...so mY should too.

mX.setX(5);
mX.getX(); // 5
mX.say(); // 5 (MyX)
mX.printValue(10); // value: 10 - x: 5

mY.setX(15);
mY.getX(); // 15
mY.say(); // 15 (MyX) (MyY)
mY.printValue(10); // value: 10 - x: 15 (MyY)
// mY inherits from BaseY, so this works:
mY.shout(); // 15!!

Я попытался создать интерфейс, которыйвсе методы по умолчанию:

interface BaseXMethods extends X {
    public default void say() { System.out.println(getX()); }
}

interface BaseYMethods extends Y { ... }

class BaseX implements BaseXMethods {
    ...
}

class MyY extends MyX implements BaseYMethods { ... }

но мне все еще нужно реализовать методы получения, установки и конструкторы, что утомительно:

class BaseX implements BaseXMethods {
    private int x;
    public BaseX(int x) {setX(x); /* or maybe call an init method from superinterface */}

    public int getX() {return x;}
    public int setX(int x) {this.x = x;}
}

class BaseY extends BaseX implements BaseYMethods {
    private int y;
    public BaseY(int x) {super(x); setY(0);}
    public BaseY(int x, int y) {super(x); setY(y);}

    public int getY() {return y};
    public void setY(int y) {this.y = y;}
}

Есть ли лучший способ?

...