NOTE: This is only a brainstorming document. It is not meant to finalize any syntax or approach.
The idea is to put everything related to a class and it's subclasses into a control table. This differs from our prior approach in that:
Example "Animals" Table
| Subclass | Sound | FoodType | Domestic | Train |
|---|---|---|---|---|
| define default | "I have no sound" | % notrain() | ||
| define evaluator | playsound(@) | |||
| define assignor | % if not in(@,"Y","N") {raiseErr()} else {return @} |
|||
| Wolf | howl | carn. | N | |
| Rat | % rodentsound() | misc. | N | |
| Cow | moo | herb. | Y | |
| Dog | ruf ruf | misc. | Y | % while not trained{try(); reward()} |
The blue shaded rows represent "definition" subclasses. In our code version they are combined into a single class definition.
The "@" symbol represents the value looked up from the relevant subclass. The percent symbol represents that a method/function is to supply the value of the attribute or method instead of a value. Notice how the Rat sound is calculated instead of hardwired into the table. The distinction between a method and an attribute are blurred. (These symbols are only preliminary suggestions.)
The "evaluator" row triggers whenever the corresponding method is called:
Cow.sound()Here, "playsound()" is executed in this case with the cow's sound string passed to it. However, if we did:
x = Cow.soundthen only "moo" is returned. If we did:
x = Rat.soundthen rodentSound() would be executed in order to generate the value. If we requested:
Rat.sound()then both rodentSound() and playSound() would be executed. It would be roughly equivalent to:
playSound(rodentSound())
The "assignor" row evaluates whenever an assignment is made to a subclass. For example, if:
Dog.domestic = "Z"is attempted, then an error is triggered because the corresponding assignor cell performs a validation.
Now for the code version:
class Animals {
method Sound {
temp = @
if empty(temp) { // implement default
temp = "I have no sound"
}
return playsound(temp)
}
method required FoodType {
return @
}
method required Domestic {
return @
}
method assignor Domestic {
if not in(@,"Y","N")
{raiseErr()} else {return @}
}
method Train {
if empty(@) {
return notrain()
} else {
return @
}
}
} // end class
subclass Wolf extends animals {
method sound {return "howl"}
method foodtype {return "carn."}
method domestic {return "N" }
}
subclass Rat extends animals {
method sound {return rodentsound() }
method foodtype {return "misc." }
method domestic {return "N" }
}
subclass Cow extends animals {
method sound {return "moo"}
method foodtype {return "herb."}
method domestic {return "Y"}
}
subclass Dog extends animals {
method sound {return "ruf ruf"}
method foodtype {return "misc."}
method domestic {return "Y"}
method train {return while not trained{try(); reward()} }
}