Наследование от двух классов Java - PullRequest
2 голосов
/ 09 июля 2011

Я знаю, что Java запрещает наследование от нескольких классов и позволяет реализовать любое количество интерфейсов.Однако, хотя интерфейсы хороши для полиморфизма, они не могут содержать никакого реального кода, которым их подклассы могут захотеть поделиться.Что если у меня есть два разных суперкласса с общим кодом, который я хочу использовать в своем подклассе?

Пример: в моей программе есть два суперкласса, один из которых работает с HashMaps, а другой - со строкамиу обоих есть прямые подклассы, и там все в порядке.Но теперь у меня есть третий, который требует общих функций обоих суперклассов, но он может расширять только один.Есть ли простой способ изменить структуру этого класса без дублирования большого количества кода?

Ответы [ 5 ]

12 голосов
/ 09 июля 2011

Использовать делегирование, а не наследование:

public class Third implements FirstInterface, SecondInterface {
    private First first;
    private Second second;

    public void foo() {
        first.foo();
    }

    public String bar() {
        return second.bar();
    }
}
6 голосов
/ 09 июля 2011

Я видел, как это сделал

  1. Извлечение интерфейса из обоих суперклассов
  2. Создание класса, реализующего интерфейсы, затем делегирование всех вызовов фактическим объектам

    public interface IFirst { public void foo(); }
    
    public interface ISecond { public void bar(); }
    
    public class Third implements IFirst, ISecond {
        private IFirst first;
        private ISecond second;
    
        public Third(IFirst first, ISecond second) {
            this.first = first;
            this.second = second;
        }
    
        @Override
        public void foo() {
            first.foo();
        }
        @Override
        public String bar() {
            return second.bar();
        }
    }
    

Этот не не даст вам доступ к защищенным членам класса heirarchy. Если это то, что вы ищете, вам не повезло в Java. Однако это позволит вам ссылаться на этот объект как на IFirst, так и на ISecond, используя полиморфно. Таким образом, вы сможете получить к нему доступ во внешнем коде, который требует один из двух типов.

Примечание: я украл наименование у JB.

2 голосов
/ 09 июля 2011

Использовать композицию - в основном, заставьте ваш новый класс расширять один из классов и иметь переменную-член в новом классе, который имеет тип суперкласс 2. Или вы можете просто пройтись по цели и использовать композицию в новом классе и иметь члены типа class1 и class2 в них

1 голос
/ 09 июля 2011

Один из подходов к этой проблеме - отдать предпочтение композиции перед наследованием.Если вы можете спроектировать два класса, из которых вы в настоящее время хотите расширяться, чтобы они могли использоваться в качестве членов вашего нового класса, тогда вы должны иметь необходимую гибкость.Вместо

class MyClass extends MapBehavior, StringBehavior { ... }

попробуйте

class MyClass {
    MapBehavior mb;
    StringBehavior sb;
    ...
}
1 голос
/ 09 июля 2011

Я подвергаю сомнению любой дизайн, в котором есть такая большая взаимозависимость между классами, которые управляют hashmaps, и классами, которые управляют строками. Но чтобы ответить на ваш вопрос напрямую, вы можете сделать свой третий класс Facade , который обернет экземпляры обоих ваших суперклассов, а затем сделать его методы делегированными этим классам соответствующим образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...