"Является ли" против "Имеет": какой из них лучше?
Портфолио А → Фонд 1
Портфолио А → Фонд 2
Портфолио А → Фонд 3
Я не мог сформулировать свое предложение, не используя is/has. Но между 1 и 2,
1) имеет:
class PortfolioA
{
List<Fund> obj;
}
2) является:
class PortfolioA : List<Fund>
{
}
какой из них вы считаете лучше с точки зрения расширяемости, удобства использования? Я все еще могу получить доступ к своим средствам в любом случае, хотя и с небольшим синтаксическим изменением.
8 ответов
Я голосую с другими людьми, которые говорят, что HAS-A лучше в этом случае. Вы спрашиваете в комментарии:
Когда я говорю, что Портфолио - это просто набор средств, с несколькими собственными атрибутами, такими как TotalPortfolio и т. д., разве это принципиально не становится "is-a"?
Я так не думаю. Если вы говорите Portfolio
ЭТО List<Fund>
А как насчет других свойств Портфолио? Конечно, вы можете добавить свойства в этот класс, но точно ли моделировать эти свойства как свойства Списка? Потому что это в основном то, что вы делаете.
И что делать, если требуется, чтобы портфолио поддерживало более одного List<Fund>
? Например, у вас может быть один Список, который показывает текущий баланс инвестиций, но другой Список, который показывает, как инвестируются новые вклады. А как насчет того, когда средства прекращаются, и для их замены используется новый набор средств? Историческая информация полезна для отслеживания, а также текущего распределения средств.
Дело в том, что все эти свойства не являются правильно свойствами Списка, хотя они могут быть свойствами Портфеля.
Не "всегда" одобряйте композицию или наследование или наоборот; они имеют различную семантику (значения); внимательно посмотрите на значения, а затем решите - не имеет значения, является ли один "легче", чем другой, для долговечности важно, чтобы вы правильно поняли семантику
помните: is-a = type, has-a = сдерживание
так что в этом случае портфель логически представляет собой совокупность средств; сам портфель не является типом фонда, поэтому состав - это правильные отношения
РЕДАКТИРОВАТЬ: Первоначально я неправильно понял вопрос, но ответ остается тем же. Портфолио - это не тип списка, это отдельная сущность со своими собственными свойствами. Например, портфель - это совокупность финансовых инструментов с первоначальными инвестиционными затратами, общей текущей стоимостью, историей значений во времени и т. Д., А список - это простая коллекция объектов. Портфель - это "тип списка" только в самом абстрактном смысле.
РЕДАКТИРОВАТЬ 2: подумайте об определении портфеля - он, без исключения, характеризуется как набор вещей. Портфолио художника - это коллекция его произведений, портфолио веб-дизайнера - это коллекция их веб-сайтов, портфолио инвестора состоит из всех принадлежащих им финансовых инструментов и так далее. Очевидно, что нам нужен список (или какой-то другой) для представления портфеля, но это никоим образом не означает, что портфель - это тип списка!
Предположим, мы решили позволить Портфолио наследовать от List. Это работает до тех пор, пока мы не добавим Запас, Связку или Драгоценный Металл в Портфолио, а затем неожиданно неправильное наследование перестанет работать. Или предположим, что нас просят смоделировать, скажем, портфель Билла Гейтса, и найти, что List не хватит памяти;-) Более реалистично, после будущего рефакторинга мы, вероятно, обнаружим, что мы должны наследовать от базового класса, такого как Asset, но если мы уже унаследовали от List, тогда мы не можем.
Резюме: различайте структуры данных, которые мы выбираем для представления концепции, и семантику (иерархию типов) самой концепции.
Первый, потому что вы должны стараться отдавать предпочтение композиции, а не наследованию.
Это зависит от того, определяет ли бизнес Портфолио как группу (и только группу) фондов. Если есть даже отдаленная вероятность того, что он может содержать другие объекты, скажем, "свойство", тогда перейдите к варианту 1. Перейдите к варианту 2, если существует тесная связь между группой фондов и концепцией портфеля.
Поскольку расширяемость и полезность 1 имеет небольшое преимущество перед 2. Я действительно не согласен с концепцией, что вы всегда должны отдавать предпочтение одному над другим. Это действительно зависит от того, что представляют собой реальные концепции реальной жизни. Помните, вы всегда можете рефакторинг.
^ Для большинства случаев всегда. Если это обнародовано, то, очевидно, нет.
Я бы выбрал вариант (1) - состав, поскольку у вас могут появиться атрибуты, специфичные для портфеля, а не для фондов.
Я буду отличаться от того, что кажется общим мнением. В этом случае я думаю, что портфель - это немного больше, чем набор средств... Используя наследование, вы разрешаете использовать несколько конструкторов, как в
public Portfolio(CLient client) {};
public Portfolio(Branch branch, bool Active, decimal valueThreshold)
{
// code to populate collection with all active portfolios at the specified branch whose total vlaue exceeds specified threshold
}
и индексаторы как в:
public Fund this[int fundId] { get { return this.fundList[fundId]; } }
и т. д.
если вы хотите иметь возможность обрабатывать переменные типа Portfolio как совокупность средств со связанным синтаксисом, то это лучший подход.
Portfolio BobsPortfolio = new Portfolio(Bob);
foreach (Fund fund in BobsPortfolio)
{
fund.SendStatement();
}
или тому подобное
Отношение IS-A представляет наследство, а отношение HAS-A представляет композицию. Для вышеупомянутого сценария мы предпочитаем композицию, так как у PortfolioA есть список, а это не тип списка. Наследование используется, когда Портфолио A является типом Списка, но здесь это не так. Следовательно, для этого сценария мы должны предпочесть композицию.