System classes and methods: Difference between revisions
m (Create page about system classes) |
m (SOUL replaces UL) |
||
(11 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
__TOC__ | |||
==Overview== | ==Overview== | ||
The ability to define classes in <var class="product">SOUL</var> is a powerful facility. However, some classes are likely to be extremely heavily accessed, require access to facilities not directly accessible in <var class="product">SOUL</var>, or both. It is for such cases that '''system classes''' were created. | |||
A system class is a class that is built into the <var class="product">[[Model 204]]</var> nucleus and is typically written in Assembler language. As such, these classes are very efficient and provide an object-oriented interface to the <var class="product">Model 204</var> kernel. Because these classes are not written in <var class="product">SOUL</var>, however, the class definitions are not available in <var class="product">SOUL</var>, so the documentation must be consulted to determine the methods available in each class. | |||
A system class is a class that is built into the [[Model 204]] nucleus and is typically written in Assembler language. As such, these classes are very efficient and provide an object-oriented interface to the Model 204 kernel. Because these classes are not written in | |||
Some | Some system classes are available to all users licensed for version 7.5 or higher of <var class="product">Model 204</var>, and some system classes are tied to another product and so only available to users licensed for that product. For example, the system <var>Socket</var> class is only available to users licensed for <var class="product">[[Janus Sockets]]</var>. | ||
All the system classes for which a user is authorized are available in any | All the system classes for which a user is authorized are available in any <var class="product">SOUL</var> request and do not need to be declared. To use a system class, simply declare an object of that class. For example, the <var>[[Stringlist class|Stringlist]]</var> class implements what is effectively an unbounded array of strings. To use this class, just declare a <var>Stringlist</var> object: | ||
< | <p class="code">%list is object stringlist | ||
%list is object stringlist | |||
... | ... | ||
%list = new | %list = new | ||
%list:add('First item') | %list:add('First item') | ||
%list:add('Second item') | %list:add('Second item') | ||
</ | </p> | ||
Some system classes have shared methods and, like user classes, | Some system classes have shared methods and, like user classes, | ||
these can be accessed with any object of the class or with the | these can be accessed with any object of the class or with the class name in parentheses. | ||
class name in parentheses. | For example, the <var>[[MaxItemLength (Stringlist property)|MaxItemLength]]</var> property in the <var>Stringlist</var> class | ||
For example, the [[MaxItemLength (Stringlist property)|MaxItemLength | returns the maximum length of any <var>Stringlist</var> item. | ||
returns the maximum length of any Stringlist item. | |||
Since this length does not depend on a particular instance, it is a shared method and can be accessed as such: | Since this length does not depend on a particular instance, it is a shared method and can be accessed as such: | ||
< | <p class="code">print %(Stringlist):maxItemLength | ||
print %(Stringlist):maxItemLength | |||
... | ... | ||
%list is object stringList | %list is object stringList | ||
print %list:maxItemLength | print %list:maxItemLength | ||
</ | </p> | ||
There are already a large number of system classes, and their number is | There are already a large number of system classes, and their number is expected to grow over time. | ||
expected to grow over time. | This raises the question of what happens when a new system class with the same name as a [[Classes and Objects|user class]] becomes available. For example, suppose there was already a user-written <var>Stringlist</var> class when the system class of the same name became available. What would be made of the following code? | ||
This raises the question of what happens when a new system class with the same name as a [[Classes and Objects| | <p class="code">class stringList | ||
< | |||
class stringList | |||
... | ... | ||
end class | end class | ||
... | |||
%list is object stringList | %list is object stringList | ||
</ | </p> | ||
The answer is that the code would continue to work as it had before. This is because it is perfectly valid to declare a | The answer is that the code would continue to work as it had before. This is because it is perfectly valid to declare a user class with the same name as a system class, and in such situations, all references to the class name are assumed to refer to the user class. To access the system <var>Stringlist</var> class in this situation, you precede the class name with <code>system:</code> wherever it appears: | ||
< | <p class="code">%systemList is object system:stringList | ||
%systemList is object system:stringList | |||
... | ... | ||
print %(system:Stringlist):maxItemLength | print %(system:Stringlist):maxItemLength | ||
</ | </p> | ||
The | The <code>system:</code> prefix can be used, of course, regardless of whether a user class by the same name exists. In fact, some sites may wish to adopt a local standard that all system class references must be preceded by <code>system:</code> to make clear what they are and to avoid confusion with user-written classes. That said, it is probably best to avoid the names of system classes when declaring user classes. | ||
Except for the way they are defined, system classes behave exactly | Except for the way they are defined, system classes behave exactly | ||
like | like user-written classes: | ||
<ul> | <ul> | ||
<li>Object variables are declared, constructed (New), and discarded in the same way. | <li>Object variables are declared, constructed (New), and discarded in the same way. </li> | ||
<li>Object variables of a system class can be declared inside a | |||
<li>Null tests and comparisons on system objects work the same way as for | <li>Object variables of a system class can be declared inside a user class or structure. </li> | ||
<li>System object variables can be passed as parameters, and methods on system objects can be strung together. | |||
<li>Null tests and comparisons on system objects work the same way as for user objects. </li> | |||
<li>System object variables can be passed as parameters, and methods on system objects can be strung together. </li> | |||
</ul> | </ul> | ||
One distinction between | One distinction between user classes and system classes is that the system class methods do not have explicit declarations. | ||
class methods do not have explicit declarations. | So the only way to understand the return values and parameters to a system method is through the documentation. | ||
So the only way to understand the return values and parameters to a system | |||
method is through the documentation. | |||
For documentation purposes, all system method parameters and return values | For documentation purposes, all system method parameters and return values | ||
(or inputs and outputs) can be thought of as having one of four basic types: | (or inputs and outputs) can be thought of as having one of four basic types: | ||
<table | |||
<tr><th | <table> | ||
<tr><th><var>Object</var></th> | |||
<td>Some method outputs or inputs are objects of a particular class. The input and output classes will be specified in the documentation.</td></tr> | <td>Some method outputs or inputs are objects of a particular class. The input and output classes will be specified in the documentation.</td></tr> | ||
<tr><th | |||
<td>All numeric input and outputs can be thought of as being declared as Float. Of course, Model 204's handling of Float values makes a Float input or output suitable even where only integral values are expected.</td></tr> | <tr><th><var>Float</var></th> | ||
<tr><th | <td>All numeric input and outputs can be thought of as being declared as <var>Float</var>. Of course, <var class="product">Model 204</var>'s handling of <var>Float</var> values makes a <var>Float</var> input or output suitable even where only integral values are expected.</td></tr> | ||
<td>Any input or output that is a string, even if it is guaranteed to be shorter than 256 bytes should be considered a | |||
<tr><th | <tr><th><var>Longstring</var></th> | ||
<td>Identical to | <td>Any input or output that is a string, even if it is guaranteed to be shorter than 256 bytes should be considered a <var>[[Longstrings|Longstring]]</var>. <var>Longstring</var> values are treated differently in certain expressions and have different truncation behavior than other <var>String</var> values — they will cause request cancellation if assigned to something that requires the <var>Longstring</var> to be truncated.</td></tr> | ||
<tr><th><var>Unicode</var></th> | |||
<td>Identical to <var>Longstring</var> except the character set is considered to be the double-byte Unicode character set. <var>Unicode</var> variables and values are passed as Unicode parameters without any conversion, while all other values are converted to an EBCDIC string as needed, and then converted to <var>Unicode</var> using the Online's EBCDIC to Unicode translation tables. Any untranslatable EBCDIC string results in a request canceling error. | |||
</table> | </table> | ||
The one exception to this simple picture is the | |||
and output from [[Collections|collection classes]]. | The one exception to this simple picture is the <var>Item</var> input and output from [[Collections|collection classes]]. | ||
Methods in collection classes behave as if any item input or output | Methods in collection classes behave as if any item input or output | ||
was an assignment to or from the item class type. | was an assignment to or from the item class type. | ||
To illustrate the importance of this distinction, consider the following | To illustrate the importance of this distinction, consider the following code: | ||
code: | <p class="code">%list is object stringList | ||
< | |||
%list is object stringList | |||
%string is string len 10 | %string is string len 10 | ||
Line 85: | Line 82: | ||
%list:add('The bear went over the mountain') | %list:add('The bear went over the mountain') | ||
%string = %list:item(1) | %string = %list:item(1) | ||
</ | </p> | ||
In this example, the last assignment would result in a request cancellation | In this example, the last assignment would result in a request cancellation | ||
because, even though the first Stringlist item is only 31 bytes long, it | because, even though the first <var>Stringlist</var> item is only 31 bytes long, it | ||
is a | is a <var>Longstring</var> value so causes request cancellation when truncated on assignment. | ||
assignment. | |||
On the other hand consider the following: | On the other hand consider the following: | ||
< | <p class="code">%list is collection arrayList of string len 255 | ||
%list is collection arrayList of string len 255 | |||
%string is string len 10 | %string is string len 10 | ||
Line 100: | Line 95: | ||
%list:add('The bear went over the mountain') | %list:add('The bear went over the mountain') | ||
%string = %list:item(1) | %string = %list:item(1) | ||
</ | </p> | ||
In this case the last assignment does not cause request cancellation, because | In this case the last assignment does not cause request cancellation, because | ||
it acts like an assignment from a String Len 255 variable to a String Len 10 | it acts like an assignment from a <code>String Len 255</code> variable to a <code>String Len 10</code>, | ||
which results in silent truncation of the input. | which results in silent truncation of the input. | ||
==Using system classes instead of $functions== | ==Using system classes instead of $functions== | ||
There are several suites of $functions that are heavily used at many | There are several suites of $functions that are heavily used at many | ||
sites that "behave badly" in an object-oriented environment, especially inside | sites that "behave badly" in an object-oriented environment, especially inside non-shared methods. | ||
non-shared methods. | For example, the [[$lists|$list]] suite of $functions do not work well inside of methods. | ||
For example, the $list suite of $functions do not work well inside of methods. | |||
You might want a $list for each instance of a class, and | You might want a $list for each instance of a class, and | ||
it might seem logical to do something like the following: | it might seem logical to do something like the following: | ||
< | <p class="code">class section | ||
class section | |||
public | public | ||
constructor new | constructor new | ||
Line 123: | Line 116: | ||
end constructor | end constructor | ||
end class | end class | ||
</ | </p> | ||
The preceding code would compile without errors and actually work, more or less | The preceding code would compile without errors and actually work, more or less | ||
correctly, as long as only a single instance of the class is created. | correctly, as long as only a single instance of the class is created. | ||
Unfortunately, if a second instance of the class were created, | Unfortunately, if a second instance of the class were created, | ||
the | the <code>$listnew</code> in the <code>New</code> constructor for the object would return the same $list identifier as | ||
in the New constructor for the object would return the same $list identifier as | for the first instance, and it would cause any data in the $list for the first instance to be deleted. | ||
for the first instance, and it would cause any data in the $list for the first | |||
instance to be deleted. | |||
Furthermore, since both objects would have the same $list identifier, they would | Furthermore, since both objects would have the same $list identifier, they would | ||
be sharing the same $list, which is not likely to be what was intended. | be sharing the same $list, which is not likely to be what was intended. | ||
The Stringlist class avoids these problems: | The <var>Stringlist</var> class avoids these problems: | ||
< | <p class="code">class section | ||
class section | |||
public | public | ||
constructor new | constructor new | ||
Line 145: | Line 135: | ||
end constructor | end constructor | ||
end class | end class | ||
</ | </p> | ||
Clearly, the code is no more complicated than the $list version, but by | Clearly, the code is no more complicated than the $list version, but by | ||
using a system object, the statement | using a system object, the statement <code>%list = new</code> creates a | ||
new Stringlist instance for each instance of the Section class, thereby | new <var>Stringlist</var> instance for each instance of the <code>Section</code> class, thereby | ||
solving the problem with the $list version. | solving the problem with the $list version. | ||
In addition, the Stringlist object is strongly datatyped, so users | In addition, the <var>Stringlist</var> object is strongly datatyped, so users | ||
or maintainers of the class have a clearer sense of the function of | or maintainers of the class have a clearer sense of the function of the <code>List</code> variable. | ||
the List variable. | Also, errors such as assigning a number to that <code>List</code> | ||
Also, errors such as assigning a number to that List | |||
variable are caught at compile-time. | variable are caught at compile-time. | ||
Finally, use of an object in this context makes it possible to | Finally, use of an object in this context makes it possible to | ||
take advantage of the better object-oriented syntax for stringing methods: | take advantage of the better object-oriented syntax for "stringing" methods: | ||
< | <p class="code">%calculus is object section | ||
%calculus is object section | |||
... | ... | ||
%calculus:list:add(%student) | %calculus:list:add(%student) | ||
</ | </p> | ||
The system classes that replace existing handle-based suites | The system classes that replace existing handle-based suites of $functions are: | ||
of $functions are: | <table> | ||
<table | <tr><th><var>[[Recordset class|Recordset]]</var>, <var>[[Record class|Record]]</var>, <var>[[SortedRecordset class|SortedRecordset]]</var>, <var>[[RecordsetCursor class|RecordsetCursor]]</var></th> | ||
<tr><th | <td>Replace traditional <var class="product">SOUL</var> file-oriented facilities.</td></tr> | ||
<td>Replace traditional | |||
<tr><th | <tr><th><var>Socket</var></th> | ||
<td>Replaces $Sockets. Only available to licensees of | <td>Replaces $Sockets. Only available to licensees of [[Janus Sockets]].</td></tr> | ||
<tr><th | |||
<td>Replaces $ | <tr><th><var>[[Stringlist class|Stringlist]]</var></th> | ||
<tr><th | <td>Replaces $lists.</td></tr> | ||
<tr><th><var>[[XmlDoc class|XmlDoc]]</var>, <var>[[XmlNode class|XmlNode]]</var>, <var>[[XmlNodelist class|XmlNodelist]]</var></th> | |||
<td>Replace $XML_ $functions. Only available to licensees of [[Janus SOAP]].</td></tr> | <td>Replace $XML_ $functions. Only available to licensees of [[Janus SOAP]].</td></tr> | ||
</table> | </table> | ||
Other system classes are | Other system classes are included in the [[Lists of classes and methods]]. | ||
==Constant methods== | ==Constant methods== | ||
Constant methods are methods that belong to system classes but are unique | Constant methods are methods that belong to system classes but are unique | ||
because they are evaluated at compilation time. | because they are evaluated at compilation time. | ||
Line 202: | Line 191: | ||
</pre> | </pre> | ||
Also, a statement like | Also, a statement like <code>%x = 1234:x</code> is '''not''' allowed, | ||
is '''not''' allowed, | |||
because a Constant method requires the constant to have the correct | because a Constant method requires the constant to have the correct | ||
datatype (in this case, String). | datatype (in this case, String). | ||
Line 210: | Line 198: | ||
replaced by the constant result of the evaluation, and all intermediate | replaced by the constant result of the evaluation, and all intermediate | ||
work quads/variables are deleted. | work quads/variables are deleted. | ||
Thus, | Thus, <code>'0d25':x</code> is basically a hex constant. | ||
The | The following are the available Constant methods: | ||
<div class="showVisit"> | |||
< | |||
<table class="wikitable"> | <table class="wikitable"> | ||
<tr><th | <tr class="head"><th>Method</th><th>Description</th></tr> | ||
<td> | |||
<tr>< | <tr><td>[[U (String function)|U function]]</td><td>Converts an EBCDIC string to a Unicode string </td></tr> | ||
<td> | |||
<tr><td>[[X (String function)|X function]]</td><td>Returns the unencoded value of a hex-encoded string</td></tr> | |||
</table> | </table> | ||
</div> | |||
</ | |||
[[Category:SOUL object-oriented programming topics]] | |||
Latest revision as of 20:16, 16 May 2016
Overview
The ability to define classes in SOUL is a powerful facility. However, some classes are likely to be extremely heavily accessed, require access to facilities not directly accessible in SOUL, or both. It is for such cases that system classes were created.
A system class is a class that is built into the Model 204 nucleus and is typically written in Assembler language. As such, these classes are very efficient and provide an object-oriented interface to the Model 204 kernel. Because these classes are not written in SOUL, however, the class definitions are not available in SOUL, so the documentation must be consulted to determine the methods available in each class.
Some system classes are available to all users licensed for version 7.5 or higher of Model 204, and some system classes are tied to another product and so only available to users licensed for that product. For example, the system Socket class is only available to users licensed for Janus Sockets.
All the system classes for which a user is authorized are available in any SOUL request and do not need to be declared. To use a system class, simply declare an object of that class. For example, the Stringlist class implements what is effectively an unbounded array of strings. To use this class, just declare a Stringlist object:
%list is object stringlist ... %list = new %list:add('First item') %list:add('Second item')
Some system classes have shared methods and, like user classes, these can be accessed with any object of the class or with the class name in parentheses. For example, the MaxItemLength property in the Stringlist class returns the maximum length of any Stringlist item. Since this length does not depend on a particular instance, it is a shared method and can be accessed as such:
print %(Stringlist):maxItemLength ... %list is object stringList print %list:maxItemLength
There are already a large number of system classes, and their number is expected to grow over time. This raises the question of what happens when a new system class with the same name as a user class becomes available. For example, suppose there was already a user-written Stringlist class when the system class of the same name became available. What would be made of the following code?
class stringList ... end class ... %list is object stringList
The answer is that the code would continue to work as it had before. This is because it is perfectly valid to declare a user class with the same name as a system class, and in such situations, all references to the class name are assumed to refer to the user class. To access the system Stringlist class in this situation, you precede the class name with system:
wherever it appears:
%systemList is object system:stringList ... print %(system:Stringlist):maxItemLength
The system:
prefix can be used, of course, regardless of whether a user class by the same name exists. In fact, some sites may wish to adopt a local standard that all system class references must be preceded by system:
to make clear what they are and to avoid confusion with user-written classes. That said, it is probably best to avoid the names of system classes when declaring user classes.
Except for the way they are defined, system classes behave exactly like user-written classes:
- Object variables are declared, constructed (New), and discarded in the same way.
- Object variables of a system class can be declared inside a user class or structure.
- Null tests and comparisons on system objects work the same way as for user objects.
- System object variables can be passed as parameters, and methods on system objects can be strung together.
One distinction between user classes and system classes is that the system class methods do not have explicit declarations. So the only way to understand the return values and parameters to a system method is through the documentation.
For documentation purposes, all system method parameters and return values (or inputs and outputs) can be thought of as having one of four basic types:
Object | Some method outputs or inputs are objects of a particular class. The input and output classes will be specified in the documentation. |
---|---|
Float | All numeric input and outputs can be thought of as being declared as Float. Of course, Model 204's handling of Float values makes a Float input or output suitable even where only integral values are expected. |
Longstring | Any input or output that is a string, even if it is guaranteed to be shorter than 256 bytes should be considered a Longstring. Longstring values are treated differently in certain expressions and have different truncation behavior than other String values — they will cause request cancellation if assigned to something that requires the Longstring to be truncated. |
Unicode | Identical to Longstring except the character set is considered to be the double-byte Unicode character set. Unicode variables and values are passed as Unicode parameters without any conversion, while all other values are converted to an EBCDIC string as needed, and then converted to Unicode using the Online's EBCDIC to Unicode translation tables. Any untranslatable EBCDIC string results in a request canceling error. |
The one exception to this simple picture is the Item input and output from collection classes. Methods in collection classes behave as if any item input or output was an assignment to or from the item class type. To illustrate the importance of this distinction, consider the following code:
%list is object stringList %string is string len 10 %list = new %list:add('The bear went over the mountain') %string = %list:item(1)
In this example, the last assignment would result in a request cancellation because, even though the first Stringlist item is only 31 bytes long, it is a Longstring value so causes request cancellation when truncated on assignment.
On the other hand consider the following:
%list is collection arrayList of string len 255 %string is string len 10 %list = new %list:add('The bear went over the mountain') %string = %list:item(1)
In this case the last assignment does not cause request cancellation, because
it acts like an assignment from a String Len 255
variable to a String Len 10
,
which results in silent truncation of the input.
Using system classes instead of $functions
There are several suites of $functions that are heavily used at many sites that "behave badly" in an object-oriented environment, especially inside non-shared methods. For example, the $list suite of $functions do not work well inside of methods. You might want a $list for each instance of a class, and it might seem logical to do something like the following:
class section public constructor new variable list is float end public constructor new %list = $listnew end constructor end class
The preceding code would compile without errors and actually work, more or less
correctly, as long as only a single instance of the class is created.
Unfortunately, if a second instance of the class were created,
the $listnew
in the New
constructor for the object would return the same $list identifier as
for the first instance, and it would cause any data in the $list for the first instance to be deleted.
Furthermore, since both objects would have the same $list identifier, they would be sharing the same $list, which is not likely to be what was intended. The Stringlist class avoids these problems:
class section public constructor new variable list is object stringlist end public constructor new %list = new end constructor end class
Clearly, the code is no more complicated than the $list version, but by
using a system object, the statement %list = new
creates a
new Stringlist instance for each instance of the Section
class, thereby
solving the problem with the $list version.
In addition, the Stringlist object is strongly datatyped, so users
or maintainers of the class have a clearer sense of the function of the List
variable.
Also, errors such as assigning a number to that List
variable are caught at compile-time.
Finally, use of an object in this context makes it possible to
take advantage of the better object-oriented syntax for "stringing" methods:
%calculus is object section ... %calculus:list:add(%student)
The system classes that replace existing handle-based suites of $functions are:
Recordset, Record, SortedRecordset, RecordsetCursor | Replace traditional SOUL file-oriented facilities. |
---|---|
Socket | Replaces $Sockets. Only available to licensees of Janus Sockets. |
Stringlist | Replaces $lists. |
XmlDoc, XmlNode, XmlNodelist | Replace $XML_ $functions. Only available to licensees of Janus SOAP. |
Other system classes are included in the Lists of classes and methods.
Constant methods
Constant methods are methods that belong to system classes but are unique because they are evaluated at compilation time. These methods require constant inputs and may have no parameters, but they have no run-time overhead.
For example, the following Constant method sets %x to a string with hex value x'0678':
%x = '0678':x
The hex conversion is done at compilation time. The method in this example (named X) is a compile-time-only equivalent of the intrinsic String class HexToString method.
As other intrinsic methods, the term "method object" is used for the constant value to which a Constant method is applied, even though the value is not really an object.
Unlike other intrinsic methods, Constant methods may be invoked only against constants. A variable as method object is not allowed:
%x = %y:x
Also, a statement like %x = 1234:x
is not allowed,
because a Constant method requires the constant to have the correct
datatype (in this case, String).
Once a Constant method is evaluated, the expression compilation is
replaced by the constant result of the evaluation, and all intermediate
work quads/variables are deleted.
Thus, '0d25':x
is basically a hex constant.
The following are the available Constant methods:
Method | Description |
---|---|
U function | Converts an EBCDIC string to a Unicode string |
X function | Returns the unencoded value of a hex-encoded string |