interface Fizz {} interface Buzz {} class CFizz() satisfies Fizz { shared actual String string = "Fizz"; } class CBuzz() satisfies Buzz { shared actual String string = "Buzz"; } class CFizzBuzz() satisfies Fizz & Buzz { shared actual String string = "FizzBuzz"; } Fizz|Buzz|Natural fizzIt(Natural i) { if ((i % 3 == 0) && (i % 5 == 0)) { return CFizzBuzz(); } else if (i % 5 == 0) { return CBuzz(); } else if (i % 3 == 0) { return CFizz(); } else { return i; } } shared void FizzBuzz06() { for (i in 1..100) { print(fizzIt(i).string); } }
The particular typing feature I am using is called "Union Types." When you declare a type as
TypeA|TypeB
(note the pipe between the two types) you are telling the Ceylon compiler that you will have either TypeA
or TypeB
, it doesn't matter. And you won't have TypeC
(for this example TypeC
is not a TypeA
or TypeB
). Without this construct I would be forced to declare the return type of fizzIt
to be an Object
and hope no stray classes like Klang
shows up.There also exists Intersection Types (
TypeA&TypeB
) which means that the type is both of TypeA
and TypeB
without having to create some other interface that joins the two. Instead of createing a new interface RunnableFuture<V>
you would just have Runnable&Future<V>
without the need for a third class. Throw in stuff like RunnableScheduledFuture<V>
which could have been declared as Runnable&Delayed&Future<V>
and the code savings start piling up.
No comments:
Post a Comment