Почему я не могу написать "реализует AClass" в Java? - PullRequest
4 голосов
/ 15 января 2011

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

Этот тип дублирования «на всякий случай» не будет необходим, если Java разрешит использовать класс в качестве интерфейса, например: class MyScanner extends MyStuff implements java.util.Scanner.Также это облегчит ситуацию, когда мне нужно предоставить тип класса, но я не хочу расширять этот класс.

Как я понимаю, «реализация класса» будет отвергнута не только компилятором, но итакже JVM (если я взломал это объявление в файл классов).Есть ли какие-то технические трудности для этого или это не считается важной вещью?Это не похоже на проблему обратной совместимости (я имею в виду, старый код работал бы нормально, если бы JVM поддерживал это).

РЕДАКТИРОВАТЬ: для пояснения я скопирую здесь гораздо лучшую формулировку StriplingWarrior с теми же вопросами:

Почему класс не может "реализовать" контракт метода другого класса без фактического расширения этого класса?Это техническая проблема?Может ли это как-то открыть нам некоторые проблемы, которые ОП не может предвидеть?

Ответы [ 3 ]

9 голосов
/ 15 января 2011

Правильно ли я понимаю, что MyClass implements AClass будет означать, что MyClass должен обеспечивать (или наследовать) реализации для всех открытых методов, которые есть у AClass? То есть каждый класс неявно определяет интерфейс, состоящий из его открытых методов?

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

Таким образом, у вас есть очень конкретная причина, по которой ваше предложение будет неверным: вы никогда не сможете добавить какой-либо открытый метод к любому классу, не рискуя нарушить некоторый код, implements этого класса. А с другой стороны, какие проблемы это решит? Дублирование кода, когда у вас есть интерфейс с одной реализацией? Как насчет решения этого, не делая этого? IMO - это обычно что-то, что люди делают TDD догматично, используя устаревшие фреймворки для насмешек, которые не способны насмехаться над конкретными классами.

5 голосов
/ 15 января 2011

Проблема в множественном наследовании . Если вы попытаетесь расширить или реализовать два класса, возможны семантические проблемы.

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

1 голос
/ 15 января 2011

Как было сказано ранее, именно так определяется стандарт, и я не могу участвовать в процессе принятия решений, используя только мои 0,02 доллара.

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

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

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

ClassA a = new ClassA();

вместо

InterfaceA a = new ClassA();

Это может привести к неожиданному поведению.

...