Narrowing assignments and class tests: Difference between revisions
mNo edit summary |
|||
(10 intermediate revisions by 4 users not shown) | |||
Line 37: | Line 37: | ||
to <code>%pouchy</code> would fail and the request would be cancelled. | to <code>%pouchy</code> would fail and the request would be cancelled. | ||
__TOC__ | |||
==Working with a pseudo-method== | ==Working with a pseudo-method== | ||
As shown in the preceding example, narrowing assignment cannot be done by a simple assignment of object variables (<code>%furry</code> to <code>%pouchy</code>, above). | As shown in the preceding example, narrowing assignment cannot be done by a simple assignment of object variables (<code>%furry</code> to <code>%pouchy</code>, above). | ||
Line 82: | Line 84: | ||
extension class. | extension class. | ||
The <code>(mammal)</code> indicates selection of a member of a base class. | The <code>(mammal)</code> indicates selection of a member of a base class. | ||
==Using the Is Instance Of operator== | ==Using the Is Instance Of operator== | ||
You might want to do narrowing assignments on the basis of the | You might want to do narrowing assignments on the basis of the | ||
Line 121: | Line 123: | ||
<br>'''Note:''' | <br>'''Note:''' | ||
No system classes currently are <var>Allow Narrow</var> classes. | No system classes currently are <var>Allow Narrow</var> classes. | ||
==See also== | |||
<ul> | |||
<li>[[Inheritance and polymorphism]] | |||
<li>[[Dynamic dispatch]] | |||
<li>[[Enhancement methods]] | |||
<li>[[Object oriented programming in SOUL]] | |||
</ul> | |||
[[Category:Overviews]] | [[Category:Overviews]] | ||
[[Category:SOUL object-oriented programming topics]] |
Latest revision as of 13:12, 22 January 2023
As discussed in "Polymorphism", Sirius Mods Version 6.9 introduced class test and narrowing assignment capabilities to the Janus SOAP ULI. As stated in that discussion, class tests and narrowing assignments should not be done lightly and, in fact, should be avoided as much as possible. For this reason, by default, class tests and narrowing assignments are not allowed for any class.
If class tests or narrowing assignments are unavoidable for a class, however, an
Allow Narrow clause must be placed in the Public block of that
base class.
For example, the Mammal
class could have the following:
class mammal public allow narrow variable weight is float variable name is string len 32 variable home is string len 32 ... end public end class
Then, if you have a class Marsupial
that extends the Mammal
class,
you could do something like the following:
%pouchy is object marsupial %furry is object mammal ... if %furry:name = 'Skippy' then %pouchy = %furry:(marsupial) end if
In this example, if earlier lines in the program did not make
%furry
actually reference a Marsupial
object,
and it simply referenced a simple Mammal
object or, perhaps, some other
extension of class Mammal
(say object Feline
), the assignment of %furry
to %pouchy
would fail and the request would be cancelled.
Working with a pseudo-method
As shown in the preceding example, narrowing assignment cannot be done by a simple assignment of object variables (%furry
to %pouchy
, above).
It has to be indicated by a pseudo-method consisting
of the target class name in parentheses.
The term pseudo-method is used because no actual code is executed in
the (marsupial)
operation and no transformation of the input
object is performed — if %furry
references a marsupial, the
operation would succeed, otherwise it would fail.
The narrowing pseudo-method will always fail if the source object is
null.
With this syntax, you can string member names to a narrowing
assignment pseudo-method.
For example, if the Marsupial
class in the above example had a PouchSize
member, you can do something like this:
if %furry:name = 'Skippy' then print %furry:(marsupial):pouchSize end if
You can also pass a narrowing assignment pseudo-method output as a method parameter:
%zoo:addMarsupial(%furry:(marsupial))
You can even do something as silly as this:
print %furry:(marsupial):(mammal)weight
This (marsupial)
does a narrowing assignment of %furry
to
an internal work variable.
Then, the (mammal)weight
accesses the Mammal
base class
member Weight
via that variable.
Of course, the above is identical to:
print %furry:weight
with the exception that the silly example would cancel the request
if %furry
did not reference a marsupial.
It is worth emphasizing that the (marsupial)
and the
(mammal)
in the above example serve two very different
functions.
The (marsupial)
indicates a narrowing assignment to an
extension class.
The (mammal)
indicates selection of a member of a base class.
Using the Is Instance Of operator
You might want to do narrowing assignments on the basis of the
class of the object pointed to by an object variable.
In the above example, %furry
is declared as being a Mammal
object
but, via polymorphism, can be pointing at an object of some extension
class, including, of course, class Marsupial
.
You can use the Is Instance Of keywords to
test whether the underlying object referenced by an object variable
is of a specific class.
The following is an example using Is Instance Of:
%pouchy is object marsupial %furry is object mammal ... if %furry is instance of marsupial then %pouchy = %furry:(marsupial) end if
In fact, you can perform class-specific processing based on such tests:
%furry is object mammal ... if %furry is instance of marsupial then %furry:home = 'Australia' end if
This kind of code is strongly discouraged, and it is a formula for long-term code maintainability problems. What will happen to the above code, for example, when used on an opossum, which is one of the few marsupials that doesn't necessarily live in Australia?
The Is Instance Of keywords must be followed by the name of a class
that is an extension class of the type of the object variable that
precedes the keywords.
Note:
No system classes currently are Allow Narrow classes.