Methods are blocks of code specific to a class. They can be thought of as providing the actions that a class instance can be told to do.
Methods can take zero or a number of parameters passed to them and may return a value.
Methods within a class are defined using the keyword def.
If not explicitly specified, the returnType of a method is void (i.e nothing returned) and the access modifiers are public, virtual.
Like variables, if the name is prefixed with an _ its access modifier defaults to protected and it is directly accessable from within the class method code.
If the name is prefixed with __ its access modifier defaults to private.
Without either of those prefixes on the name of the method, the accessType is public, virtual and
it must be accessed from within method code by prefixing the name with either this. or just . (dot) .
def <methodName> [as <returnType>] [is <AccessModifiers>] [has <Attributes>] [<DocString>] def <methodName>(<paramList>) [as <returnType>] [is <AccessModifiers>] [has <Attributes>] [<DocString>]
A parameter list is a comma separated list of name (and optionally type and parameter description modifier) specifications
<paramName> [as [<paramDesc>] <Type>] [, ...]
<paramDesc> is optional and may be vari and/or a parameter direction indicator out or inout ( default if unspecified is in)
vari indicates the parameter name is a placeholder for a variable length arglist. Within the method this may be unpacked/accessed as a list.
in (implicit) args are only passed into the method. Any changes made to the argument inside the method are not visible outside the method (pass-by-value)
out the arg is returned from the method
inout argument is both passed into the method and (any possibly changed) value is also returned from the method (pass-by-reference)
If <Type> is unspecified it is defaulted to and treated as dynamic.
def meth( a, b as String, c as out String) c = b + "_meth" def sum(a as vari int) as int sum = 0 for i in a sum += i return sum
meth takes 3 args , the first and second are inward only and are typed as dynamic and a string respectively,
the third is only returned from the method as a string.
sum takes a variable number of integer args and returns an integer.
Tests, Contracts and Code
The above refers to simple method code or method body code.
You can also specify Tests (for the method) and contract requirements on the method.
To do this the method is tagged with named clauses:
- test clauses for any tests,
- require and ensure clauses for the pre and post conditions specifying the method contracts and a
- body clause for the method code.
If given, the order of these clauses must be :
- Test clauses
- contract clauses (require and/or ensure)
- body clause
These are named methods on a class that have some special responsibility or relationship to the Object Model
(they were originally implemented as methods with special names but have since been redone specified as cues
- Initializer init
The initializer (or constructor) method of a class is a special method named init which is implicitly called when a class instance is constructed. It's responsible for setting the contents of a class instance to an initial state. It doesnt return any value and is not inherited (i.e baseclass initialization must be done with an explicit call to a baseclass constructor).
If an init method is not specified the compiler runtime generates a noArg constructor that does nothing (changed - this was original behaviour, now an init method must be explicitly provided).
Constructor chaining can be done to another constructor in the same class (usually with a different number or Type of args) or to a Superclass constructor (using base.init) - this call must be the first executable line in the init method.
- Destructor finalize
- HashCode calculation hash hash as int
- Comparison compare compare(other) as int
- Equality equals equals(other) as int
- Enumerator enumerate enumerate as T*
A method body is the code that implements the methods actions or behaviour.
In addition to the body, a methods contents may also include optional contracts specifications
(pre method entry prerequisite conditions and post method exit postconditions ) and/or optional Test clauses.
Contract prerequisites are tagged with the keyword suffix require.
Postconditions are suffixed with keyword ensure.
Both of these may be a single expression (on the same line as keyword) or an indented clause on line following the keyword.
(see wiki:Contracts for an expanded description)
Tests are always in an indented clause following the test suffix keyword.
If tests or contracts are specified and any of these are indented clauses
(i.e if any tests are given (always in an indented clause) or single or multiple prerequisite or postcondition expressions are given (in an indented clause)
then the method body must also be tagged with the keyword suffix body and the method body code placed in a following indented clause.
def simpleBump(i as int) as int require i >0 # prerequisite contract - single expression .counter += 1 # method body starts here - not indented .val += i return .val def simpleBump(i as int) as int require i >0 # prerequisite contract - single expression ensure .val > old .val # postcondition contract - single expression .counter += 1 # method body - not additionally indented .val += i return .val def simpleBump(i as int) as int test # unit test clause a = Inst() assert a.counter == 0 assert a.val == 0 a.simpleBump(1) assert a.counter ==1 assert a.val == 1 body ##method body - tagged and additionally indented .counter += 1 .val += i return .val def simpleBump(i as int) as int require # prerequisite contract - in indented clause (1 or many expressions) i >0 body # method body must be tagged and indented .counter += 1 .val += i return .val # this emits a syntax error - method body must be tagged and indented def simpleBump(i as int) as int require # prerequisite contract - in indented clause (1 or many expressions) i >0 .counter += 1 #method body - not additionally indented .val += i return .val # Heres a full example giving all the clauses def simpleBump(i as int) as int require # prerequisite contract - in indented clause (1 or many expressions) i >0 ensure # postcondition contract - in indented clause (1 or many expressions) .val > old .val test # unit test clause a = Inst() assert a.counter == 0 assert a.val == 0 a.simpleBump(1) assert a.counter ==1 assert a.val == 1 test num2 # another unit test clause (named) a = Inst() a.simpleBump(2) assert a.counter == 1 assert a.val == 2 body #method body - tagged and additionally indented .counter += 1 .val += i return .val
Return to LanguageTopics