Обмануть одинарное наследование в Яве?

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

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

Это совсем другая мысль.

Warrior 04.12.2008 11:34
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
8
1
4 754
13
Перейти к ответу Данный вопрос помечен как решенный

Ответы 13

JAVA не поддерживает множественное наследование.

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

Обычно, когда кто-то предлагает множественное наследование в C# или JAVA, это связано с тем, что «они могли» в C++. Я фанат фразы «просто потому, что ты не можешь этого сделать, не значит, что ты должен». Поскольку C# и JAVA его не поддерживают, зачем пытаться заставить его делать то, для чего он не предназначен. Это не означает, что существуют уникальные случаи, когда это действенный метод эмполии, просто код обычно можно отредактировать, чтобы он не нуждался в нем.

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

Jon Limjap 16.09.2008 13:03

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

Calum 16.09.2008 13:06

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

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

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

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

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

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

Paul de Vrieze 16.09.2008 14:38

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

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

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

Да, это «изящный трюк», но его не стоит использовать в производственном коде!

Calum 16.09.2008 13:17

но для использования прокси вам нужны интерфейсы. ОП: "... без использования интерфейса ..."

user85421 13.05.2009 13:02

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

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

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

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

Я подумал об этом немного больше и понял, что, хотя динамические прокси будут работать (это то, как RMI (используется?) Для работы), если вам действительно нужна такая функциональность, вам лучше взглянуть на аспектно-ориентированное программирование (AOP), используя что-то вроде AspectJ (eclipse.org/aspectj).

Таким образом, вы можете получить несколько различных аспектов в классе, давая вам псевдомиксиновое наследование, без ужасно хрупкой иерархии наследования.

Как уже отмечали все остальные, желание / необходимость множественного наследования обычно указывает на то, что вы не подходите к проблеме с правильной точки зрения. Вспомните для начала принцип GoF «предпочитать композицию наследованию»!

Была попытка внедрить миксины в Java. Проверьте эту ссылку: http://www.disi.unige.it/person/LagorioG/jam/

Ответ принят как подходящий

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

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

здесь небольшая опечатка, я бы исправил это, но у меня пока недостаточно репутации. 'создать подклассы ТО как'

TygerKrash 21.09.2010 13:15

@TygerKrash Для редактирования сообщений репутация не нужна: SE создан как Wiki.

Yatharth Agarwal 09.01.2015 17:20

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

Используя внутренние классы, C++ иногда предпочитает именно это: Идиома внутреннего класса.

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

public class parents implements first, second{

}

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

Другие вопросы по теме