Наследование лучше, когда какое-то условие проверяет что-то присущее вашему объекту, которое вы проверяете постоянно (например, состояние или тип). В этом примере это оператор для дерева математических выражений. Оператор, как и сложение, имеет выражение до и после знака плюс ( инфиксная запись ), поэтому я называю их влево и вправо, потому что он представлен в виде дерева. Есть также унарные операторы, такие как дефис, который отрицает значение, но у него есть только одно дочернее выражение.
Использование наследования означает, что тип (упрощенный до одинарного или двоичного) учитывается в наследовании:
class Operator
{
abstract string ToString();
}
class UnaryOperator : Operator
{
Expression Expression { get; }
override string ToString() {...}
}
class BinaryOperator : Operator
{
Expression LeftExpression { get; }
Expression RightExpression { get; }
}
class AdditionOperator : BinaryOperator
{
override string ToString()
{
return this.LeftExpression.ToString() + "+" + this.RightExpression.ToString();
}
}
В отличие от:
class Operator
{
Expression LeftExpression { get; }
Expression RightExpression { get; }
OperatorType Type { get; }
string ToString()
{
switch(this.Type)
{
case OperatorType.Addition:
return this.LeftExpression.ToString() + "+" + this.RightExpression.ToString();
case OperatorType.Negation:
return "-" + this.LeftExpression.ToString();
case ...:
}
}
}
enum OperatorType
{
// Unary operators
Negation,
// Binary operators
Addition,
Subtraction,
Multiplication
}
Здесь унарный оператор не имеет выражения Left и Right, а просто выражение. Это означает, что вы должны ввести соглашение, что левый используется, а правый равен нулю. ToString должен будет проверить OperatorType; как и любой другой метод, который должен действовать в зависимости от оператора.
Последний подход чаще всего встречается в реализациях XML DOM, где XmlNode - это практически все, что может содержать любой узел XML ... когда-либо. Это делает для некоторых очень запутанных ситуаций:
- Как атрибут или текстовый узел могут иметь дочерние узлы?
- Как документ может иметь дочерние узлы, если он может иметь только один? (Это не обязательно должна быть коллекция)
- Как у документа может быть ParentNode?
- Каким образом документ может иметь значение?
- 1024 * И т.д. *