Чем в java заменить множественное наследование?

Хочу реализовать приблизительно следующую архитектуру:

Пояснение:

  • Base - Что-то вроде сущности-хранилища, в котором хранятся какие-то базовые объекты;
  • ChildN - потомки, реализующие свой спектр действий над данными, которые хранятся в классе Base. По сути являются интерфейсами, т.к. никакого состояния не хранят;
  • static Mixin - класс, объединяющий в себе все методы из ChildN. Коллизий между именами методов нет. Все его методы (т.е. методы, унаследованные от ChildN) должны быть статическими, вызываться без инстанцирования.

В эта задача легко бы решилась множественным наследованием, в такого нет. Как быть?


Примерный псевдокод того, что хочу реализовать:

class Base {
    static protected final String someString = "01";
}

class Child1 extends Base {
    static public char get_0() {
        return someString.charAt(0);
    }
}

class Child2 extends Base {
    static public char get_1() {
        return someString.charAt(1);
    }
}

class MixIn extends Child1, Child2 {  // Так сделать нельзя

}

public class Main {
    public static void main(String[] args) {
        System.out.println(MixIn.get_0());  // Итоговое использование должно быть таким
        System.out.println(MixIn.get_1());
    }
}

Ответы (1 шт):

Автор решения: Zhenyria

Как выяснилось, разделение функционала на несколько классов с повторным объединением в один нужно вам исключительно в целях логической группировки. Возможные решения вашей проблемы:


Использование интерфейсов

Вы можете сделать child-ы интерфейсами. В Java нет множественно наследования, зато можно имплементировать несколько интерфейсов. Чтобы сделать реализацию методов прямо в интерфейсах (чтобы они не требовали реализации в реализующем их классе), можно использовать ключевое слово default:

class Base {
    static public final String str = "01";
}

interface Child1 {
    default char get0() {
        return Base.str.charAt(0);
    }
}

interface Child2 {
    default char get1() {
        return Base.str.charAt(1);
    }
}

class MixIn implements Child1, Child2 {
}

class Main {
    public static void main(String[] args) {
        MixIn mixIn = new MixIn();
        System.out.println(mixIn.get0());
        System.out.println(mixIn.get1());
    }
}

Отказ от разделения функционала

Вы работаете с одним репозиторием Base. На мой взгляд здесь более чем достаточно использование одного класса без всяких интерфейсов. Более того, можно все эти методы разместить в классе Base.

Например:

class Base {
    private final String str = "01";

    public String getStr() {
        return str;
    }
}

class MixIn {
    private Base base;

    public MixIn(Base base) {
        this.base = base;
    }

    public char get0() {
        return base.getStr().charAt(0);
    }

    public char get1() {
        return base.getStr().charAt(1);
    }
}

public class Main {
    public static void main(String[] args) {
        MixIn mixIn = new MixIn(new Base());
        System.out.println(mixIn.get0());
        System.out.println(mixIn.get1());
    }
}

Использование статических внутренних классов

Вы говорите, что вам нужна логическая группировка. В Java существует конструкция, которая называется статический внутренний или вложенный класс. Внутри класса создаётся ещё один класс, который отмечается static. Таким образом вы можете достичь логической группировки. Пример:

class Base {
    static public final String someString = "01";
}

class MixIn {
    public static class Child1 {
        static char get1() {
            return Base.someString.charAt(1);
        }
    }

    public static class Child2 {
        static char get0() {
            return Base.someString.charAt(0);
        }
    }
}

Видите, я создал общий класс MixIn, а внутри него два статических класса. Вызываются они вот так:

class Main {
    public static void main(String[] args) {
        System.out.println(MixIn.Child1.get1());
        System.out.println(MixIn.Child2.get0());
    }
}

Как видите, никакого инстанцирование нет, а классы/методы логически сгруппированы.

→ Ссылка