Class button_class has static switchable with name "button", before [; Push : print "You push the ", (name) self; if (self hasnt on){ <SwitchOn self>; " on"; } <SwitchOff self>; " off"; ];Class - The word class declares a class. But a class declaration just creates a category, it does not create an object, an instance of that class. So in the above example, no actual button exists yet.
Object TVButton "TV button" class button_class with name "tv" "television"; ...or... button_class TVButton "TV button" with name "tv" "television";Class objects are created the same way regular objects are, except the class name is included. button_class on the first line is just shorthand for object, etc. class button_class on two lines. Now an actual button exists.
if (TVbutton ofclass button_class) true if a member of this class, false if not false if not a class object at all, and no error will resultA Doe Crib Note:
Just as if (object provides localproperty) can make a nice substitute for if (object has attribute) [see attributes, #4], so can if (object ofclass class). Both help "get around" that maximum number of attributes limit. |
Class button_class has static switchable with name "button", before [; Push : print "You push the ", (name) self; if (self hasnt on){ <SwitchOn self>; " on"; } <SwitchOff self>; " off"; ]; button_class TVButton "TV button" with name "tv" "television";Because the TVButton object has no before, the before of the button_class class is called. But what happens when an object has a property the class also has? This differs depending on whether the property is additive or not.
Class button_class has static switchable with name "button", before [; Push : print "You push the ", (name) self; if (self hasnt on){ <SwitchOn self>; " on"; } <SwitchOff self>; " off"; react_before [; Push : if (player in puddle) { if (self has on) "You might think twice about that."; deadflag = 1; "Sparks arc from the button to the puddle at your feet..^^"; } ]; button_class TransButton "transformer button" with name "transformer", react_before [; Push : if ((player in puddle) && (self has on)) "You get a shock and dance back."; ];When a property is non-additive, once it is included in the object, the class property will never be used/executed. So pushing the transformer button when it is on and the player is in a puddle will print, "You get a shock and dance back." But pushing the button when it isn't on and player is in a puddle and will just turn it on, because the class react_before will never be executed. However, if an object has no property of it own, then the class property will be used/executed. For instance, if the button object had no react_before...
button_class TransButton "transformer button" with name "transformer";...then the button class react_before would be executed and if the button is on and the player is in a puddle, it will print "You might think twice about that." And this time, if the button is off and the player is in a puddle, then the player will be killed. I don't know what Dr. Nelson calls this, but I call it "overwriting." When a property is non-additive, if it is included in an object it will always overwrite the class property. Also note the that whole property is non-additive, not just parts of it (i.e., the whole react_before, not Push).
name |
describe |
before |
after |
each_turn |
life |
Class button_class has static switchable with name "button", before [; Push : print "You push the ", (name) self; if (self hasnt on){ <SwitchOn self>; " on"; } <SwitchOff self>; " off"; ]; button_class TVButton "TV button" with name "tv" "television";There are only a few additive properties. They add the class' property value to the object's property value. For instance, the TVButton inherits name from the button_class, so it can be referred to as: "tv", "television", "button", "tv button", or "television button." Since the name property is not only inherited, but also additive, "tv" and "television" in the object is added to "button" in the class.
Using classes is a simple way to give things the same name distinguished only by different adjectives (television button, elevator button). This makes parsing easier and avoids the need to include more complicated parse_name routines. |
Class button_class has static switchable with name "button", before [; Push : print "You push the ", (name) self; if (self hasnt on){ <SwitchOn self>; " on"; } <SwitchOff self>; " off"; ]; Object TVButton "TV button" class button_class with name "tv" "television", before [; Push : if (self hasnt on) "You watch too much television already."; ];In a regular object, if its before routine returns true (1), then processing stops there. This is also true for an additive property. When a property is additive, if it returns true from an object, then the class property will never be used/executed. Since the TVButton's before is called first and returns true by printing a string, the button_class' before is never executed. So "You watch too much television already." will be printed and the button will not be turned on or off. To have a class property also be used/execute, then object's property must return false (0)...
Object TVButton "TV button" class button_class with name "tv" "television", before [; Push : if (self hasnt on) print "You watch too much television already. "; ];...or the "superclass" operator that Dr. Nelson has provided can be used. Changing string to print, just prints the string and returns false, so the object message will be printed and the button will be turned on or off along with printing the class message. Taken all together it will appear on the screen as -- "You watch too much television already. You push the TV button on." (or "off").
object.class::property;The superclass operator calls a class property directly, so it can reverse the normal object/class property call order. Thus, it can be used to: 1. prevent a class non-additive property being overwritten 2. execute a class additive property first, only executing the object additive property next if some conditions in the class weren't met.
Class button_class has static switchable with name "button", before [; Push : print "You push the ", (name) self; if (self hasnt on){ <SwitchOn self>; " on"; } <SwitchOff self>; " off"; react_before [; Push, Touch : if (player in puddle) { if (self has on) "You might think twice about that."; deadflag = 1; "Sparks arc from the button to the puddle at your feet..^^"; } ]; button_class TransButton "transformer button" has on with name "transformer", react_before [; Push : if ((player in puddle) && (self has on)) "You get a shock and dance back."; self.button_class::react_before(); default : if (action~=##Examine) self.button_class::react_before(); ];Remember, a whole property is non-additive, not just parts of it -- so it doesn't matter if a particular action returns 1 or 0, once the property is present in the object it completely overwrites the class property. But including the superclass operator can force a call of a class non-additive property. When this is done then the object property return value matters, because the superclass operator will only be used as long as the object property doesn't return 1 before invoking it.
Class button_class has static switchable with name "button", before [; Push : if (self hasnt on) <SwitchOn self>; <SwitchOff self>; Touch : if ((player in puddle) && (self has on)) "You get a shock and dance back."; ]; button_class TVButton "TV button" has on with name "tv" "television", before [; Push : self.button_class::before(); "You push ", (the) self, "."; ];For Push, the superclass operator would call the class before first and because it returns 0, the rest of the object before would be executed next. If the class before returned 1, the rest of the object before would not executed. This just reverses the normal order of calling class properties. Touch is unaffected, because before is an additive property and the object before has no response for Touch. When an object has no response for an additive property it automatically calls the class property to get its response.
Class button_class has static switchable with name "button", description [; print "The ", (name) self, " is "; if (self has on) "on."; "off."; ], before [; Push : print "You push the ", (name) self; if (self hasnt on){ <SwitchOn self> " on."; <SwitchOff self>; " off"; ]; Object TVButton "TV button" class button_class with name "tv" "television"; Object VCRButton "VCR button" class button_class with name "VCR";In an object, self refers to that particular object. In a class declaration, self refers to whichever class object the class is currently processing. So pushing the TVButton turns it on or off and prints, "You push the the TV button on." (or "off"). Pushing the VCRButton turns it on or off and prints, "You push the VCR button on." (or "off"). Examining the TVButton prints "The TV button is on." (or "off). Examining the VCRButton prints "The VCR button is on." (or "off'). It's another one of those classy features.
Use (name) self in a class declaration instead of the usual (the) self, to get the current object's name to print correctly. A classy idiosyncrasy. |
Command | Example |
---|---|
class
(declares a class) |
Class button_class |
class
(in an object, makes that object a member of that class) |
Object TVButton "TV Button" class button_class |
class name
(in an object, makes that object a member of that class, same as above) |
button_class TVButton "TV Button" |
ofclass
(tests an object's class membership) |
if (TVButton ofclass button_class) |
self
(in a class declaration, refers to the class object currently being processed by the class) |
print "You push the ", (name) self, "."; |
object.class::property
(calls a class property directly -- superclass operator) |
TVButton.button_class::before(); |
additive properties |
name describe after before each_turn life |