Состав и наследование одинаковы? Если я хочу реализовать шаблон композиции, как я могу сделать это в Java?
208
Состав и наследование одинаковы? Если я хочу реализовать шаблон композиции, как я могу сделать это в Java?
Ответы:
Они абсолютно разные. Наследование - это отношения "есть" . Композиция "есть" .
Вы создаете композицию, имея экземпляр другого класса
C
в качестве поля вашего класса вместо расширенияC
. Хороший пример, где состав был бы намного лучше, чем наследованиеjava.util.Stack
, в настоящее время расширяетсяjava.util.Vector
. Это сейчас считается ошибкой. Вектор стека "НЕ-НЕ" ; Вы не должны иметь права вставлять и удалять элементы произвольно. Это должна была быть композиция вместо этого.К сожалению, уже слишком поздно исправлять эту ошибку проектирования, поскольку изменение иерархии наследования теперь нарушит совместимость с существующим кодом. Если бы
Stack
вместо наследования использовалась композиция, ее всегда можно изменить, чтобы использовать другую структуру данных, не нарушая API .Я очень рекомендую книгу Джоша Блоха Effective Java 2nd Edition
Хороший объектно-ориентированный дизайн не связан с расширением существующих классов. Ваш первый инстинкт должен сочинять вместо этого.
Смотрите также:
источник
Композиция означает
HAS A
наследование средства
IS A
Example
: У автомобиля есть двигатель, а у автомобиля - автомобильВ программировании это представляется как:
источник
:-/
type
поле ТипаEnum
Насколько наследование может быть опасным?
Давайте возьмем пример
1) Как ясно из вышеприведенного кода, класс Y имеет очень сильную связь с классом X. Если что-то изменится в суперклассе X, Y может резко сломаться. Предположим, что в будущем класс X реализует метод работы с подписью ниже
Изменение сделано в классе X, но это сделает класс Y некомпилируемым. Так что такая зависимость может подняться на любой уровень, и это может быть очень опасно. Каждый раз, когда суперкласс может не иметь полной видимости кода внутри всех его подклассов, и подкласс может постоянно замечать, что происходит в суперклассе все время. Поэтому нам нужно избегать этой сильной и ненужной связи.
Как композиция решает эту проблему?
Давайте посмотрим, пересмотрев тот же пример
Здесь мы создаем ссылку на класс X в классе Y и вызываем метод класса X, создавая экземпляр класса X. Теперь все эти сильные связи исчезли. Суперкласс и подкласс теперь очень независимы друг от друга. Классы могут свободно вносить изменения, которые были опасны в ситуации наследования.
2) Второе очень хорошее преимущество композиции в том, что оно обеспечивает гибкость вызова метода, например:
В классе Test, используя ссылку r, я могу вызывать методы класса X, а также класса Y. Эта гибкость никогда не была в наследстве
3) Еще одно большое преимущество: модульное тестирование
В приведенном выше примере, если состояние экземпляра x неизвестно, его можно легко смоделировать, используя некоторые тестовые данные, и все методы можно легко протестировать. Это было невозможно вообще при наследовании, так как вы сильно зависели от суперкласса, чтобы получить состояние экземпляра и выполнить любой метод.
4) Еще одна веская причина, по которой мы должны избегать наследования, заключается в том, что Java не поддерживает множественное наследование.
Давайте рассмотрим пример, чтобы понять это:
Хорошо знать :
состав легко достигается во время выполнения, в то время как наследование предоставляет свои возможности во время компиляции
состав также известен как отношение HAS-A, а наследование также известно как отношение IS-A
Так что сделайте это привычкой всегда предпочитать композицию наследованию по разным причинам.
источник
Ответ, который дал @Michael Rodrigues, неправильный (извиняюсь; я не могу комментировать напрямую), и может привести к некоторой путанице.
Реализация интерфейса - это форма наследования ... когда вы реализуете интерфейс, вы не только наследуете все константы, вы делаете свой объект того типа, который определен интерфейсом; это все еще отношения " есть ". Если в машине реализован Fillable , автомобиль « is-a » Fillable и может использоваться в вашем коде везде, где вы используете Fillable .
Композиция принципиально отличается от наследования. Когда вы используете композицию, вы (как отмечается в других ответах) устанавливаете отношение « есть » между двумя объектами, в отличие от отношения « есть », которое вы устанавливаете при использовании наследования .
Итак, из примеров автомобилей в других вопросах, если бы я хотел сказать, что у автомобиля есть «бензобак», я бы использовал композицию следующим образом:
Надеюсь, это прояснит любое недоразумение.
источник
Наследование выявляет отношения IS-A . Композиция выявляет отношения HAS-A . Шаблон стратегии объясняет, что композиция должна использоваться в тех случаях, когда существуют семейства алгоритмов, определяющих конкретное поведение.
Классическим примером является класс утки, который реализует летное поведение.
Таким образом, мы можем иметь несколько классов, которые реализуют полет, например:
Если бы это было по наследству, у нас было бы два разных класса птиц, которые снова и снова выполняют функцию мухи. Так что наследование и состав совершенно разные.
источник
Композиция такая же, как кажется - вы создаете объект, подключая части.
РЕДАКТИРОВАТЬ остальную часть этого ответа ошибочно основан на следующей предпосылке.
Это достигается с помощью интерфейсов.
Например, используя
Car
пример выше,Таким образом, с помощью нескольких стандартных теоретических компонентов вы можете создать свой объект. Тогда ваша задача - заполнить информацию о том, как
House
защищает своих обитателей и какCar
защищает своих обитателей.Наследование как и наоборот. Вы начинаете с завершенного (или полу-завершенного) объекта и заменяете или переопределяете различные биты, которые хотите изменить.
Например,
MotorVehicle
может прийти сFuelable
методом иDrive
методом. Вы можете оставить метод Fuel таким, какой он есть, потому что он одинаков для заправки мотоцикла и автомобиля, но вы можете переопределитьDrive
метод, потому что мотоцикл движется совсем иначе, чем aCar
.С наследованием некоторые классы уже полностью реализованы, а у других есть методы, которые вы вынуждены переопределить. С Композицией вам ничего не дано. (но вы можете реализовать интерфейсы, вызывая методы в других классах, если у вас что-то есть).
Композиция выглядит более гибкой, потому что если у вас есть метод, такой как iUsesFuel, у вас может быть метод где-то еще (другой класс, другой проект), который просто заботится о работе с объектами, которые можно заправлять, независимо от того, является ли это автомобилем, лодка, печь, барбекю и т. д. Интерфейсы требуют, чтобы классы, которые говорят, что они реализуют этот интерфейс, на самом деле имеют методы, о которых этот интерфейс - все. Например,
тогда вы можете иметь метод где-то еще
Странный пример, но он показывает, что этот метод не заботится о том, что он заполняет, потому что объект реализует
iUsesFuel
, он может быть заполнен. Конец истории.Если бы вместо этого вы использовали Inheritance, вам потребовались бы другие
FillHerUp
методы,MotorVehicles
иBarbecues
если у вас не было достаточно странного базового объекта «ObjectThatUsesFuel» для наследования.источник
ThisCase
, а не вcamelCase
. Поэтому лучше называть свои интерфейсыIDrivable
и т. Д. Вам может не понадобиться «I», если вы правильно перегруппировали все свои интерфейсы в пакет.Они не одинаковы.
Композиция : она позволяет обрабатывать группу объектов так же, как отдельный экземпляр объекта. Назначение составной части состоит в том, чтобы «объединять» объекты в древовидные структуры для представления иерархий части-целого
Наследование : класс наследует поля и методы от всех своих суперклассов, прямых или косвенных. Подкласс может переопределять методы, которые он наследует, или он может скрывать поля или методы, которые он наследует.
Статья в Википедии достаточно хороша для реализации составного шаблона в Java.
Ключевые участники:
Компонент :
Лист :
Композитный :
Пример кода для понимания составного шаблона:
вывод:
Объяснение:
Обратитесь к приведенному ниже вопросу о преимуществах и недостатках композиции и наследования.
Предпочитаете композицию наследству?
источник
в качестве другого примера, рассмотрим класс автомобиля, это было бы хорошим использованием композиции, автомобиль "имел бы" двигатель, трансмиссию, шины, сиденья и т. д. Он не расширял бы ни один из этих классов.
источник
Композиция - это то, где что-то состоит из отдельных частей, и она тесно связана с этими частями. Если основная часть умирает, так же как и остальные, они не могут жить своей собственной жизнью. Грубый пример - человеческое тело. Выньте сердце, и все остальные части умрут.
Наследование - это то, где вы просто берете то, что уже существует, и используете это. Там нет прочных отношений. Человек может унаследовать имущество своего отца, но он может обойтись без него.
Я не знаю Java, поэтому не могу привести пример, но могу дать объяснение понятий.
источник
Наследование между двумя классами, когда один класс расширяет другой класс, устанавливает отношения « IS A ».
Композиция на другом конце содержит экземпляр другого класса в вашем классе, который устанавливает отношение « Имеет А ». Композиция в Java полезна, поскольку она технически облегчает множественное наследование.
источник
В Простом Слове Агрегация означает Имеет Отношения ..
Композиция является частным случаем агрегации . Более конкретно, ограниченная агрегация называется составом. Когда объект содержит другой объект, если содержащийся объект не может существовать без существования контейнерного объекта, он называется композицией. Пример: класс содержит студентов. Студент не может существовать без класса. Между классом и учениками существует композиция.
Зачем использовать агрегацию
Повторное использование кода
Когда используется агрегация
Повторное использование кода также лучше всего достигается с помощью агрегации, когда нет корабля отношений
наследование
Наследование - это наследование отношений между родителями и ребенком.
Наследование в Java - это механизм, в котором один объект приобретает все свойства и поведение родительского объекта.
Использование наследования в Java 1 Code Reusability. 2 Добавьте дополнительную функцию в дочерний класс, а также переопределение метода (чтобы можно было достичь полиморфизма во время выполнения).
источник
Хотя и Наследование, и Композиция обеспечивают возможность повторного использования кода, основное отличие Композиции от Наследования в Java заключается в том, что Композиция позволяет повторно использовать код без его расширения, но для Наследования вы должны расширить класс для любого повторного использования кода или функциональности. Другое отличие, вытекающее из этого факта, состоит в том, что с помощью Composition вы можете повторно использовать код даже для конечного класса, который не является расширяемым, но Inheritance не может повторно использовать код в таких случаях. Также с помощью Composition вы можете повторно использовать код из многих классов, поскольку они объявлены как просто переменные-члены, но с помощью Inheritance вы можете повторно использовать код только для одного класса, потому что в Java вы можете расширить только один класс, потому что множественное наследование не поддерживается в Java , Вы можете сделать это в C ++, потому что один класс может расширять несколько классов. Кстати, вы должны всегдаЯ предпочитаю композицию наследованию в Java , это не только я, но даже Джошуа Блох предложил в своей книге
источник
Я думаю, что этот пример ясно объясняет различия между наследованием и составом .
В этом примере проблема решается с использованием наследования и композиции. Автор обращает внимание на то, что; в наследовании изменение в суперклассе может вызвать проблемы в производном классе, которые наследуют его.
Там вы также можете увидеть разницу в представлении, когда вы используете UML для наследования или композиции.
http://www.javaworld.com/article/2076814/core-java/inheritance-versus-composition--which-one-should-you-choose-.html
источник
Наследование против композиции.
Наследование и композиция используются для повторного использования и расширения поведения класса.
Наследование в основном используется в модели программирования семейного алгоритма, такой как тип отношения IS-A, означает похожий тип объекта. Пример.
Они принадлежат семье автомобилей.
Композиция представляет тип отношения HAS-A. Она показывает способность объекта, такого как Duster, имеет пять Gears, Safari имеет четыре Gears и т. Д. Когда нам нужно расширить возможности существующего класса, используйте композицию. Например, нам нужно добавить еще одну шестеренку в объект Duster, затем мы должны создать еще один объект шестеренки и скомпоновать ее с объектом Duster.
Мы не должны вносить изменения в базовый класс до тех пор, пока / если все производные классы не нуждаются в этих функциях. Для этого сценария мы должны использовать Composition.Such как
класс A, полученный классом B
Класс A, полученный классом C
Класс A Производный от класса D.
Когда мы добавляем какую-либо функциональность в класс A, она становится доступной для всех подклассов, даже если классы C и D не требуют этих функциональных возможностей. Для этого сценария нам нужно создать отдельный класс для этих функциональных возможностей и объединить его с требуемым классом ( здесь класс B).
Ниже приведен пример:
источник
Композиция означает создание объекта для класса, который имеет отношение к этому конкретному классу. Предположим, что учащийся имеет отношение к счетам;
Наследование, это предыдущий класс с расширенной функцией. Это означает, что этот новый класс является старым классом с некоторыми расширенными возможностями. Предположим, ученик - ученик, но все ученики - люди. Так что есть отношения со студентом и человеком. Это наследство.
источник
Нет, оба разные. Композиция следует отношениям "HAS-A", а наследование - отношениям "IS-A". Лучшим примером для композиции был стратегический шаблон.
источник
Наследование означает повторное использование всей функциональности класса. Здесь мой класс должен использовать все методы суперкласса, и мой класс будет аккуратно связан с суперклассом, и код будет продублирован в обоих классах в случае наследования.
Но мы можем преодолеть все эти проблемы, когда используем композицию для общения с другим классом. Композиция объявляет атрибут другого класса в моем классе, с которым мы хотим поговорить. и какую функциональность мы хотим от этого класса мы можем получить с помощью этого атрибута.
источник