Есть ли разница между
public class A extends AbstractB implements C
{...}
против...
public class A extends AbstractB
{...}
abstract class AbstractB implements C
{...}
Я понимаю, что в обоих случаях класс А в конечном итоге будет соответствовать интерфейсу. Во втором случае AbstractB
может обеспечить реализацию методов интерфейса в C
. Это единственная разница?
Если я не хочу , чтобы обеспечить реализацию любого из методов интерфейса в AbstractB
, какой стиль я должен использовать ? Имеет ли использование того или иного скрытую цель «документирования»?
java
interfaces
abstract-class
c_maker
источник
источник
Ответы:
Все зависит от того,
AbstractB implements C
семантически ли . Т.е., если это имеет смысл семантически дляAbstractB
реализацииC
, то пойти на это.Если мы возьмем конкретные примеры, семантическая разница станет очевидной.
Если A = Собака, AbstractB = Животное, C = IBark
Единственный разумный выбор
Это не имеет смысла, поскольку это подразумевает, что все животные лают.
Другие различия вступают в игру, если у вас есть больше, чем просто
class A
наследование отAbstractB
. В # 1 им не нужно реализовывать C, в # 2 все они вынуждены внедрять C.источник
Heterotroph
кажется разумным сделатьAnimal
реализациюHeterotroph
. Если вы ожидаете много других лающих животных и хотите относиться к ним таким же образом, то вам подойдет другой классBarkingAnimal extends Animal implements IBark
.Heterotroph
но спасибо за ваш вкладПростой способ определить правильные отношения наследования - это не посмотреть на сами классы, а на код, который вызывает методы этих классов. Где-то в вашем коде у вас есть что-то вроде
AbstractB b = new A();
илиotherObject.addAbstractB(this);
. В любом случае, вы позже используете этоAbstractB
ссылку для выполнения различных вызовов методов.В этой ситуации вы хотите вызвать методы
C
? Если так, тоAbstractB
следует реализоватьC
. Если нет, то не должно. Если у вас нет подобных ситуаций, тогда вам не нужно наследование, и вам следует рефакторинг, чтобы использовать композицию, потому что она гораздо слабее связана.источник
Это не «скрытая» цель документации. Это позволяет вам приводить AbstractB и все его подклассы к C. На самом деле есть три стиля.
Я бы использовал это, если бы AbstractB логически не реализовывал C. Даже если он не предоставляет методы, он может иметь значение. Таких как Собака расширяет, Животные реализуют Ваг. Это не имеет смысла для всех животных, чтобы вилять. Обратите внимание, что этот подход на самом деле не мешает AbstractB предоставлять реализацию.
Я бы использовал этот, если бы я хотел, чтобы все подклассы реализовали интерфейс И это имело бы смысл для всех них. Такие как Beagle расширяет, AbstractDog реализует Wag.
Это излишне, но может добавить ясности.
источник