Contents this "Lesson:"
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 |