type Cat = {
    getName->String
    color->String
    changeNameTo(_:String)->String
    speak->Void
    asString->String}
type Cheetah = Cat & { // object of type Cheetah must have all
    speed->Number      // of the methods specified in Cat type
    race(_:Cat)->Cat}
// Constants for use as default arguments
   
def defaultName:String = "Kitty"
def defaultColor:String = "tabby"
def defaultSpeed:Number = 70
// Constructor methods with varying parameters
method cat->Cat is public{CatClass.new(defaultColor, defaultName)}
method catOfColor(aColor:String)->Cat is public{CatClass.new(aColor, defaultName)}
method catOfColor (aColor:String) named (aName:String)->Cat is public{
    CatClass.new(aColor, aName)}
method cheetah->Cheetah is public{CheetahClass.new(defaultName, defaultSpeed)}
method cheetahNamed(aName:String)->Cheetah is public{
    CheetahClass.new(aName, defaultSpeed)}
method cheetahNamed (aName:String) withSpeed (aSpeed:Number)->Cheetah is public{
    CheetahClass.new(aName, aSpeed)}
class CatClass.new(aColor:String, aName:String){
    // a cat's color is immutable; treated as a method that returns String
    def color:String is public, readable= aColor
    // variable is private by default; don't want users to be able
    // to change the cat's name with :=
    var name:String := aName
    method getName->String is public{name}
    method changeNameTo(newName:String)->String is public{
        var oldName:String := name
        name := newName
        return oldName}
    method speak->Void is public{print "{name} says: Meow!"}
    method asString->String is public{""}
}
//alternate approach: aCat.new(c, n) equivalent to CatClass.new(c, n)
def aCat = object{
    method new(aColor:String, aName:String)-> Cat is public{
        object{
            def color:String = aColor
            var name:String := aName
            method getName->String is public{name}
            method changeNameTo(newName:String)->String is public{
                var oldName:String := name
                name := newName
                return oldName}
            method speak->Void is public{print "{name} says: Meow!"}
            method asString->String is public{""}
        }
    }
}
//an example of inheritance
class CheetahClass.new(aName:String, aSpeed:Number){
    
    //class gains all methods of an instance of CatClass
    // with color spotted and name aName
    inherits CatClass.new("spotted", aName)
    def speed:Number is public, readable = aSpeed
    // if the competitor is a cheetah, returns cat with higher speed
    // (competitor wins if the speeds are equal); otherwise, this cheetah
    // wins by default 
    method race(other:Cat)->Cat is public{
        match(other)
            case{ct:Cheetah->
                if(speed > ct.speed) then {self}
                else{ct}
            }
            case{ct:Cat-> self}
    }
   // overriding the speak and asString methods in CatClass to be more
   // apppropriate for cheetahs
    method speak->Void is public, overriding{print "{name} says: Grr."}
    method asString->String is public, overriding{""}
}