Tuesday, September 13, 2011

The Platypus

I read this in a book recently:
"Early zoologists classified as mammals those that suckled their young and as reptiles those that lay eggs. Then a duck-billed platypus was discovered in Australia laying eggs like a perfect reptile and then, when they hatched, suckling the infant platypi like a perfect mammal.

The discovery created quite a sensation! 'Why does this paradox of nature exist?'

Zoologists, to cover up their problem, had to invent a patch. They created a new order, monotremata, that includes the platypus, the spiny anteater, and that's it. This is like a nation consisting of two people."
The book is 'Lila: An Enquiry into Morals' by Robert M. Pirsig, more famous for 'Zen and the Art of Motorcycle Maintenance'. For some reason, maybe because I'd been coding that day, not unusual since I am a web developer by trade, it made me think of the canonical example of inheritance you always see:
Animal animal = new Dog();
which is described by one commentator as 'You are creating a new Dog, but then you are treating it as an Animal'. I thought it would be fun to go through that story in an object-oriented manner, and see what (unholy) code emerged.

Flickr photo
FlickrPlatypus, by Psycho Hamster

First of all, I need a base class and two interfaces
abstract class Animal() {}
interface ISuckleYoung {}
interface ILayEggs {}
such that
class Mammal() : Animal, ISuckleYoung { }
class Reptile() : Animal, ILayEggs { }
Now, classify things!
class Classification {
    void Classify() {
        Animal bear = new Mammal();
        Animal snake = new Reptile();
This builds, and I'm experiencing the satisfaction that only a Victorian taxonomist could have known. Then this happens:
class DuckBilledPlatypus : Mammal, Reptile {}
This code causes a sensation! A platypus can't derive from both a mammal and a reptile, and C# knows it. So, rolling that back, I'm left with an unclassified Platypus. There's a band name if anyone wants it.
class DuckBilledPlatypus {}
Enter the Monotremata (sing. monotreme), an order that belongs to the Mammalia class:
class Monotreme : Mammal, ILayEggs {}
They're mammals that lay eggs! This new order squeezes in between the Platypus and the Mammal/Reptile level in the hierarchy, restoring taxonomical rectitude to the situation:
class DuckBilledPlatypus : Monotreme {}
class SpinyAnteater : Monotreme {}

Generic classes

Actually, I'd rather make a monotreme a generic class:
abstract class Monotreme : Animal {}
class Monotreme<T> : Monotreme where T : Mammal, ILayEggs { }
That means we can new up monotremes like this:
var platypus = new Monotreme<DuckBilledPlatypus>();
var spinyAnteater = new Monotreme<SpinyAnteater>();
But there's something missing. There's the poetic comparison that the author makes between this whole kludge and a nation that has two people.
interface IAmLikeANationThatHasTwoPeople {}
which decorates the Monotremata order, consisting solely of platypi and anteaters, which is a just a bunch of Monotremes:
class Monotremata : List<Monotreme>, IAmLikeANationThatHasTwoPeople
    List<DuckBilledPlatypus> _platypi { get; set; }
    List<SpinyAnteater> _spinyAnteaters { get; set; }
With this hierarchical scaffolding firmly in place, zoologists can continue classifying weird animals thus:
void Classify()
    var classifiedAnimals = new List();
    Animal bear = new Mammal();
    Animal snake = new Reptile();

    var platypus = new Monotreme<DuckBilledPlatypus>();
    var spinyAnteater = new Monotreme<SpinyAnteater>();

    var monotremata = new Monotremata

"Platypi have been laying eggs and suckling their young for millions of years before there were any zoologists to come along and declare it illegal. The real mystery, the real enigma, is how mature, objective, trained scientific observers can blame their own goof on a poor innocent platypus.

The world comes to us in an endless stream of puzzle pieces that we would like to think all fit together somehow, but that in fact never do. There are always some pieces like platypi that don't fit and we can either ignore these pieces or we can give them silly explanations or we can take the whole puzzle apart and try other ways of assembling it that will include more of them."

Copyright warning!

Please, if you use this code for commercial purposes, say in some zoo or vet app or something, give credit where credit is due. That's a joke, by the way.