A method declaration declares the existence of a method for the current
object being defined. Declarations are only possible in an
interface
. The implementation
contains only method
definitions (see section Method definitions).
method_declaration: shared_method_part `;' ; shared_method_part: method_decl [pre_condition] [post_condition] ; method_decl: return_type method_qualifier* method_name_part | return_type method_qualifier* method_decl_part+ ;
In the first rule of a method_decl
, a method without any
arguments is declared. In the second case, the method does have
arguments.
method_name_part: [identifier | ...] [:] ;
A method_name_part
can be an identifier or any of the TOM
keywords, except post
and pre
. It is optionally suffixed
by a colon. A colon itself also is a valid method_name_part
.
(Usually, by convention, any method_name_part
containing a colon
indicates an optional method part for which' arguments a default value
is supplied in the declaration.)
method_qualifier: protection_qualifier | redo_qualifier | `deferred' ;
If deferred
, the method is not implemented by the current object.
The protection qualifiers (see section Encapsulation) define the
availability of this method to the current class, its subclasses and the
other classes.
redo_qualifier: `redeclare' | `redefine' ;
If a class redefines a method implemented by a super class, it must
declare the method as being redefine
d.
[Note: redeclare
is meant to allow a subclass to indicate
different object kinds for the arguments to a method implemented by a
superclass. This is not yet implemented, its precise semantics have not
yet been defined and its usefulness is being questioned. End note.]
method_decl_part: method_name_part argument_type argument_name [`=' expression] ;
If the expression
is provided it denotes a default value for the
arguments mentioned in the argument_name
. Provision of such a
default implies that this part of the method name is optional in the
invocation of this method. Note that this is fully handled by the
compiler: an invocation of a method specifying not all the arguments can
not be discerned from an invocation specifying all default values for
the arguments.
The expression
must be evaluable in every context where it is
used. It is, however, not enforced by the compiler that the expression
is evaluable in every context where it can be used. [Note: This is a
bug. End note.]
argument_name: identifier | `(' identifier_list `)' ;
If the argument_type
is not a tuple, the argument_name
should be an identifier. For a tuple type, the argument_name
should be a parenthesized identifier list, with the same number of
elements as the tuple type.
[Note: This syntax rule does not allow an element of a tuple-typed argument to be a tuple. That is wrong, but currently how it is implemented. End note.]
Given the following method declaration
int foo int a bar: (int, int) (b, c) = (0, 1);
which has one mandatory argument, a
, and one optional argument,
(b, c)
. Given a receiver rcv
of the proper type, this
method can be invoked in different ways:
[rcv foo 1]; [rcv foo 2 bar: (3, 4)]
It is considered good practice to use a colon suffix for those nameparts of a method that are optional.
Since optional method parts are a purely compile time affair, if the
object defining this foo bar:
method is also to respond to a
foo
message, the object must explicitly define that method:
<doc> Respond to `foo' in addition to `foo bar:'. </doc> int foo int a { = [self foo a bar: (0, 1)]; }
Obviously, since with one optional argument there are only two
possibilities, the foo bar:
method could just as well not have
optional arguments, their omission being handled by the foo
method. However, in the context of multiple optional arguments, the
selectors to which an object responds do become an issue.
Similarly, if a library was previously distributed with the following method declared for some class handling streams on files
instance (id) with String name input: boolean input_p = FALSE output: boolean output_p = FALSE if-not-exists: int ne_action = 0;
and the new version of the library changes this method to be
instance (id) with String name input: boolean input_p = FALSE output: boolean output_p = FALSE if-exists: int e_action = 0 if-not-exists: int ne_action = 0;
then it would be wise to incorporate a compatibility method in the new library, just to avoid having to recompile all code depending on the library, which is an issue especially in the case of shared libraries. The method below would then exist in the new library for the sole purpose of responding to the original selector.
instance (id) with String name input: boolean input_p = FALSE output: boolean output_p = FALSE if-not-exists: int ne_action = 0 { = [self with name input: input_p output: output_p if-exists: 0 if-not-exists: ne_action]; }
In a method invocation, if multiple methods match, methods with a longer
name (i.e. with more (unused) optional name parts) are preferred over
methods with a shorter name. This implies that the specification of
if-exists: 0
in the invocation in the example is unnecessary.
Go to the first, previous, next, last section, table of contents.