|
|
|
|
|
by justinpombrio
4671 days ago
|
|
Your example shows a different kind of behavior than the parent's example. A union type (t1 \/ t2) is a type that says "either this value has type t1, or it has type t2". In your example, the type of x is not (Employer \/ Employee), it is their shared superclass - Person. The analogous example would be if val x = if (some_condition) Employer else Employee
succeeded even though Employer and Employee did not share a superclass. Very few languages use union types - Typed Racket comes to mind, and Algol apparently did too. |
|
In the beginning we typed x as Employer | Employee. But, as the hierarchy grew bigger compile times became huge. Then we decided to let x be the lowest superclass of all the types in the union (and mark it with a "+", meaning: it's this class, or any subclass). This made compile times much faster, and in most (if not all) cases this is what you want when you assign different types under the same hierarchy to a variable.
What this does mean, though, is that the following won't compile:
That is, even though "x" is never assigned a Mouse, Crystal infers the type of "x" to be Animal+, so it really doesn't know which types are in and considers all cases.Again, this is most of the time something good: if you introduce a new class in your hierarchy you probably want it to respond to some same methods as the other classes in the hierarchy.