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