Предпочитаете композицию наследству?

Вы можете сохранить массив messages и рассчитать сообщение, которое будет отображаться по ходу, например:

var messages = ["Good!", "Great!", "Awesome!", "Super!", "Nice!"];
function getMessage() {
   return messages[Math.floor(Math.random() * messages.length)];
}

Попробуйте здесь , а затем просто вызовите getMessage в вашем вызове .text() , например:

label.addClass("valid").text(getMessage());

1488
задан Taryn 22 March 2017 в 16:23
поделиться

14 ответов

В Java или C#, объект не может изменить свой тип, как только это инстанцировали.

Так, если Ваша объектная потребность появиться как различный объект или вести себя по-другому в зависимости от объектного состояния или условий, то используют Состав : Обратитесь к состояние и Шаблоны разработки Стратегии .

, Если объектная потребность иметь тот же тип, то используйте Наследование или реализуйте интерфейсы.

40
ответ дан Sung M. Kim 22 March 2017 в 16:23
поделиться

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

3
ответ дан 22 March 2017 в 16:23
поделиться

Наследование очень мощно, но Вы не можете вызвать его (см.: проблема кругового эллипса ). Если Вы действительно не можете быть абсолютно уверены в истинном, "-" отношения подтипа, то лучше идти с составом.

18
ответ дан yukondude 22 March 2017 в 16:23
поделиться

Думайте о включении, как имеет отношения. Автомобиль "имеет" механизм, у человека "есть" имя, и т.д.

Думают о наследовании, как отношения. Автомобиль "является" механизмом, человек "является" млекопитающим, и т.д.

я не беру кредита на этот подход. Я взял его прямо от 110-секундного Выпуска Кода, Завершенного Steve McConnell , Раздел 6.3 .

381
ответ дан Nick Zalutskiy 22 March 2017 в 16:23
поделиться

Кроме a/has соображения, нужно также рассмотреть "глубину" наследования, которое должен пройти Ваш объект. Что-либо вне пяти или шести уровней наследования глубоко могло бы вызвать неожиданный бросок и упаковку/распаковывание проблем, и в тех случаях могло бы быть мудро составить Ваш объект вместо этого.

6
ответ дан Jon Limjap 22 March 2017 в 16:23
поделиться

Другой, очень прагматическая причина, для предпочтения состава по наследованию имеет отношение модели предметной области и отображению его к реляционной базе данных. Действительно трудно отобразить наследование на модель SQL (Вы заканчиваете со всеми видами hacky обходных решений, как создание столбцов, которые не всегда используются, с помощью представлений, и т.д.). Некоторые ORMLs пытаются иметь дело с этим, но это всегда сложно быстро. Состав может быть легко смоделирован через отношения внешнего ключа между двумя таблицами, но наследование намного более трудно.

81
ответ дан Tim Howland 22 March 2017 в 16:23
поделиться

Предпочитают состав по наследованию, поскольку это более покорно / легкий изменить позже, но не использует подход сочинения всегда. С составом, легко изменить поведение на лету с Внедрением зависимости / Методы set. Наследование более твердо, поскольку большинство языков не позволяет Вам происходить больше чем из одного типа. Таким образом, гусь более или менее приготовлен, как только Вы происходите из TypeA.

Мое испытание на кислотность для вышеупомянутого:

  • TypeB хочет представить полный интерфейс (все открытые методы не меньше) TypeA, таким образом, что TypeB может использоваться, где TypeA ожидается? Указывает Наследование .

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

  • TypeB хочет только часть/часть поведения, представленного TypeA? Указывает на потребность в [1 110] Состав.

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

Обновление: Просто возвратился к моему ответу, и это кажется теперь, когда это неполно без определенного упоминания о Barbara Liskov принцип замены Лисков как тест для, 'Я должен наследоваться этому типу?'

1103
ответ дан Galilyou 22 March 2017 в 16:23
поделиться

While in short words I would agree with "Prefer composition over inheritance", very often for me it sounds like "prefer potatoes over coca-cola". There are places for inheritance and places for composition. You need to understand difference, then this question will disappear. What it really means for me is "if you are going to use inheritance - think again, chances are you need composition".

You should prefer potatoes over coca cola when you want to eat, and coca cola over potatoes when you want to drink.

Creating a subclass should mean more than just a convenient way to call superclass methods. You should use inheritance when subclass "is-a" super class both structurally and functionally, when it can be used as superclass and you are going to use that. If it is not the case - it is not inheritance, but something else. Composition is when your objects consists of another, or has some relationship to them.

So for me it looks like if someone does not know if he needs inheritance or composition, the real problem is that he does not know if he want to drink or to eat. Think about your problem domain more, understand it better.

74
ответ дан 22 November 2019 в 20:15
поделиться

Когда вы хотите «скопировать» / раскрыть API базового класса, вы используете наследование. Если вы хотите только «скопировать» функциональность, используйте делегирование.

Один из примеров: вы хотите создать стек из списка. В стеке есть только щелчки, толчки и взгляды. Вы не должны использовать наследование, поскольку вам не нужны функции push_back, push_front, removeAt и т. Д. В стеке.

7
ответ дан 22 November 2019 в 20:15
поделиться

Если вы понимаете разницу, это проще объяснить.

Процедурный код

Примером этого является PHP без использования классов (особенно до PHP5). Вся логика закодирована в наборе функций. Вы можете включать другие файлы, содержащие вспомогательные функции и т. Д., И вести бизнес-логику, передавая данные в функциях. По мере роста приложения это может быть очень сложно. PHP5 пытается исправить это, предлагая более объектно-ориентированный дизайн.

Наследование

Это поощряет использование классов. Наследование - это один из трех принципов объектно-ориентированного проектирования (наследование, полиморфизм, инкапсуляция).

class Person {
   String Title;
   String Name;
   Int Age
}

class Employee : Person {
   Int Salary;
   String Title;
}

Это наследование в действии. Сотрудник "является" Человеком или наследуется от Человека. Все отношения наследования являются отношениями «как». Employee также затеняет свойство Title от Person, то есть Employee.Title будет возвращать Title для Employee, а не Person.

Состав

Состав предпочтительнее наследования. Проще говоря, у вас будет:

class Person {
   String Title;
   String Name;
   Int Age;

   public Person(String title, String name, String age) {
      this.Title = title;
      this.Name = name;
      this.Age = age;
   }

}

class Employee {
   Int Salary;
   private Person person;

   public Employee(Person p, Int salary) {
       this.person = p;
       this.Salary = salary;
   }
}

Person johnny = new Person ("Mr.", "John", 25);
Employee john = new Employee (johnny, 50000);

Композиция обычно «имеет» или «использует» отношения. Здесь у класса Employee есть Person. Он не наследуется от Person, а вместо этого получает объект Person, переданный ему, поэтому он «имеет» Person.

Композиция вместо наследования

Теперь предположим, что вы хотите создать тип Manager, чтобы в итоге вы получили:

class Manager : Person, Employee {
   ...
}

Этот пример будет работать нормально, однако что, если и Person, и Employee объявят Title ? Должен ли Manager.Title возвращать «Операционный менеджер» или «Мистер»? При компоновке эта неоднозначность лучше обрабатывается:

Class Manager {
   public string Title;
   public Manager(Person p, Employee e)
   {
      this.Title = e.Title;
   }
}

Объект Manager состоит из Employee и Person. Поведение Title взято от сотрудника.

204
ответ дан 22 November 2019 в 20:15
поделиться

With all the undeniable benefits provided by inheritance, here's some of its disadvantages.

Disadvantages of Inheritance:

  1. You can't change the implementation inherited from super classes at runtime (obviously because inheritance is defined at compile time).
  2. Inheritance exposes a subclass to details of its parent class implementation, that's why it's often said that inheritance breaks encapsulation (in a sense that you really need to focus on interfaces only not implementation, so reusing by sub classing is not always preferred).
  3. The tight coupling provided by inheritance makes the implementation of a subclass very bound up with the implementation of a super class that any change in the parent implementation will force the sub class to change.
  4. Excessive reusing by sub-classing can make the inheritance stack very deep and very confusing too.

On the other hand Object composition is defined at runtime through objects acquiring references to other objects. In such a case these objects will never be able to reach each-other's protected data (no encapsulation break) and will be forced to respect each other's interface. And in this case also, implementation dependencies will be a lot less than in case of inheritance.

129
ответ дан 22 November 2019 в 20:15
поделиться

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

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

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

Я бы предложил использовать компоновку по умолчанию. Он более модульный и дает преимущество позднего связывания (вы можете изменять компонент динамически). Также проще тестировать вещи по отдельности. И если вам нужно использовать метод из класса, вы не обязаны иметь определенную форму (принцип подстановки Лискова).

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

Я бы предложил использовать компоновку по умолчанию. Он более модульный и дает преимущество позднего связывания (вы можете изменять компонент динамически). Также проще тестировать вещи по отдельности. И если вам нужно использовать метод из класса, вы не обязаны иметь определенную форму (принцип подстановки Лискова).

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

Я бы предложил использовать компоновку по умолчанию. Он более модульный и дает преимущество позднего связывания (вы можете изменять компонент динамически). Также проще тестировать вещи по отдельности. И если вам нужно использовать метод из класса, вы не обязаны иметь определенную форму (принцип подстановки Лискова).

14
ответ дан 22 November 2019 в 20:15
поделиться

Чего вы хотите заставить себя (или другого программиста) придерживаться и когда вы хотите предоставить себе (или другому программисту) больше свободы. Утверждалось, что наследование полезно, когда вы хотите заставить кого-то использовать способ решения / решения конкретной проблемы, чтобы они не могли свернуть в неверном направлении.

Is-a и Has-a - полезное практическое правило.

0
ответ дан 22 November 2019 в 20:15
поделиться

Наследование - это наследование, особенно соблазнив, особенно поступает с процедурной земли, и она часто выглядит обманчиво элегантным. Я имею в виду, что все, что мне нужно сделать, это добавить это одному немного функциональности для другого класса, верно? Ну, одна из проблем состоит в том, что

Наследование, вероятно, является худшей формой муфты, которую вы можете иметь

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

Статья, Наследование - это зло: Epic Fail из даматичныхannotationsModelBinder , проходит через пример этого в C #. Это показывает использование наследства, когда должна была быть использована композиция, и как оно может быть восстановлено.

57
ответ дан 22 November 2019 в 20:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: