3 ms·
But actually in Crystal you will have the same behaviour: class Person end class Employer < Person end class Employee < Person end x = some_co
by asterite 13y ago
But actually in Crystal you will have the same behaviour:
class Person
end
class Employer < Person
end
class Employee < Person
end
x = some_condition ? Employer.new : Employee.new
# x is a Person+
This is not said in the "happy birthday" article (or anywhere else, IIRC).
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:
# Yes, there are abstract classes in Crystal
abstract class Animal
end
class Dog < Animal
def talk
end
end
class Cat < Animal
def talk
end
end
class Mouse < Animal
end
x = foo ? Dog.new : Cat.new
x.talk # undefined method 'talk' for Mouse
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.
- theseoafs 13y agoWell, the happy birthday article has a section on "union types", and that code block has the comment "# Here a can be an Int32 or Float64". I just assumed that this meant a had the type Int32 | Float64. If the language doesn't actually have union types, then the article should probably be edited to reflect that (because it's very misleading on this issue).
- asterite 13y agoIt has union types. Right now if you do 1 || 1.5 it gives you Int32 | Float64. If you do Foo.new || Bar.new, and Foo and Bar are not related (except they both inherit from Reference), then you get Foo | Bar. If Foo and Bar are related by some superclass Super, then you get Super+. If you do: a = [1, 'a', 1.5, "hello"] you get Array(Int32 | Char | Float64 | String) In a way, the Super+ type is a union type of all the subtypes of Super, including itself, but just with a shorter name.