Мир OOP на самом деле не имеет строгого аналога DU (именно поэтому его часто называют «несовершенным»), но наиболее близким является двухуровневая иерархия наследования.
Рассмотрим следующий DU:
type Shape = Circle of radius:Float | Rectangle of width:Float * height:Float
Семантику (то есть "значение") этого типа можно сформулировать примерно так: формы бывают двух видов - Circle
, который имеет радиус, и Rectangle
, который имеет ширину и высоту, и нет других видов фигур
Это будет примерно эквивалентно следующей иерархии наследования :
abstract class Shape {}
class Circle : Shape {
public double Radius { get; set; }
}
class Rectangle : Shape {
public double Width { get; set; }
public double Height { get; set; }
}
Этот фрагмент C# также смутно выражает идею о том, что формы бывают двух видов - Circle
и Rectangle
", но есть некоторые важные различия:
В будущем (или в других библиотеках) могут появиться другие виды фигур. Другие люди могут просто объявить новый класс, который наследуется от Shape
- и вот вам go. Дискриминационные союзы F # этого не допускают.
Circle
и Rectangle
являются собственными типами. Это означает, что можно объявить метод, который принимает Circle
, но не Rectangle
. F # дискриминационные союзы не позволяют этого. В F # Shape
является типом, но Circle
и Rectangle
не являются типами. Не может быть переменных, параметров или свойств типа Circle
.
F # предоставляет ряд упрощенных конструкций syntacti c для работы с DU, которые в C# имеют быть написанным очень многословно, с большим количеством шума.
Точки (1) и (2) на поверхности кажутся ограничениями (действительно, я использовал слова "делать не разрешать "в обоих случаях), но это на самом деле особенность. Идея состоит в том, что некоторые ограничения (не все) приводят к более правильным и стабильным программам. Посмотрите в прошлое: «Перейти к списку вредных», ссылки заменяют указатели, сборка мусора заменяет ручное управление памятью - все это отнимает некоторую гибкость, а иногда и производительность, но компенсирует это повышением надежности кода.
То же самое с F # DU: тот факт, что не может быть других типов фигур, кроме Circle
и Rectangle
, позволяет компилятору проверять правильность функций, работающих с Shape
- т.е. убедитесь, что все возможные случаи были обработаны. Если позже вы решите добавить третий тип фигуры, компилятор поможет найти все места, которые необходимо обработать в этом новом случае.
Третий пункт говорит о идее "сделать правильную вещь легкой и не ту вещь тяжело ". С этой целью F # предоставляет некоторый полезный синтаксис (например, сопоставление с образцом) и некоторые полезные значения по умолчанию (например, неизменяемость, структурное сравнение), которые в C# должны быть вручную закодированы и применены с дисциплиной.