Обманывать одиночное наследование в Java? - PullRequest
8 голосов
/ 16 сентября 2008

Я слышал, что есть способ обмануть одиночное наследование и реализовать множественное наследование в Java. Кто-нибудь знает, как это реализовать (без использования интерфейса)?

Просто из любопытства; -)

Ответы [ 13 ]

20 голосов
/ 16 сентября 2008

Конечно, вы можете, но это сложно, и вы должны действительно подумать, если вы хотите идти по этому пути.
Идея состоит в том, чтобы использовать наследование на основе области в сочетании с наследованием на основе типа. Это разговор типа о том, что для внутренних целей внутренние классы «наследуют» методы и поля внешнего класса. Это немного похоже на миксины, где внешний класс смешивается с внутренним классом, но не настолько безопасен, так как вы можете изменить состояние внешнего класса, а также использовать его методы.
Гилад Брача (один из главных разработчиков языка Java) написал статью , в которой это обсуждается. Итак, предположим, что вы хотите разделить некоторые методы для внутреннего использования между несколькими несвязанными классами (например, для работы со строками), вы можете создать их подклассы как внутренние классы класса, который имеет все необходимые методы, и подклассы могут использовать методы как из своих суперклассов, так и из внешнего класса.

В любом случае, это сложно для сложных классов, и вы можете получить большую часть функциональности, используя статический импорт (начиная с java 5 и далее). Отличный вопрос для собеседований и викторин в пабах; -)

5 голосов
/ 29 ноября 2008

Одиночное Многократное наследование не поддерживается Java, вместо этого у него есть интерфейсы для одинаковых целей. Если вы непреклонны в использовании множественного наследования, это должно быть сделано в C ++.

4 голосов
/ 16 сентября 2008

Использование композиции вместо наследования имеет тенденцию быть обходным путем. Это на самом деле также очень помогает с тестируемостью, так что это хорошая практика в целом.

Если вы просто хотите, чтобы ваш тип "вел себя", как несколько других типов, вы можете наследовать столько интерфейсов, сколько захотите; Вы, конечно, не можете «позаимствовать» детали реализации из них.

3 голосов
/ 16 сентября 2008

Я считаю, что основная причина того, что Java не поддерживает множественное наследование, такая же, как в C #; все объекты в конечном счете являются производными от Object, и он имеет несколько путей к одному и тому же базовому классу для компилятора неоднозначно. Неоднозначно == Плохо, поэтому компилятор не позволяет этого.

Вместо этого вы можете моделировать множественное наследование с помощью делегирования. См. эту статью для примера.

2 голосов
/ 16 сентября 2008

Вы можете немного обмануть (и я немного подчеркиваю), используя экземпляры java.lang.reflect.Proxy.

Это действительно просто позволяет вам добавлять дополнительные интерфейсы и делегировать их вызовы другому экземпляру во время выполнения.

Как человек, который наставляет и обучает новых разработчиков, я был бы в ужасе, если бы кто-нибудь показал мне код, который сделал это. Reflection - это один из тех инструментов, которые вам действительно необходимо понять и хорошо понять Java, прежде чем приступить к работе. Лично я когда-либо делал это только один раз, и это было для того, чтобы создать некоторый код, который я не мог контролировать, реализовать некоторые интерфейсы. другой код, который я не мог контролировать, ожидал (это был быстрый взлом, поэтому мне не пришлось писать и поддерживать слишком много связующего кода).

1 голос
/ 16 сентября 2008

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

1 голос
/ 16 сентября 2008

Необходимо соблюдать осторожность, чтобы отличать наследование интерфейса (по сути, наследование контракта для предоставления определенных средств) от наследования реализации (наследование механизмов реализации).

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

Наследование реализации - это механизм extends , и у вас есть только одна его версия. Вам действительно нужно множественное наследование реализации? Могу поспорить, что нет, это переполнено неприятными последствиями, если вы все равно не программист Eiffel.

1 голос
/ 16 сентября 2008

Использование interface с. Вы можете реализовать столько, сколько захотите. Обычно вы можете использовать какой-либо вариант в Composite Pattern (GoF) , чтобы иметь возможность повторно использовать код реализации, если это желательно.

0 голосов
/ 15 октября 2017

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

public class parents implements first, second{

}

но помните, вы должны переопределить методы, объявленные в интерфейсах.

0 голосов
/ 13 мая 2009

С помощью внутренних классов это то, что иногда предпочитает и C ++: Идиома внутреннего класса .

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