GOO    CLASSES

Goo's object-oriented features are used by creating a .goo file that begins with an include line "include goo-runtime". This signals Goo that OO syntax will appear, and cause it to generate a run-time include file. Classes are generated by writing class declarations followed by class bodies. If the file include's other .goo files, they are processed recursively. Include files with a .gcl extension are also processed (into .g files) in case you wish to isolate classes in their own files (reccommended).
The object features of Goo recognize the following new keywords and dot notation.




Class Declaration

The class declaration introduces a class and defines its public features. It is followed by a class body that defines private and secret features and public methods mentioned in the declaration.

Example:

class Child Begin declaration of a class named 'Child'
   inherit Base Declare 'Base' to be an ancestor.
   member pub Declare (and define) a public member 'pub'
   method pubmeth Declare (only) a public method
   virtual function fct Declare a virtual function
end class Terminate the public declaration of the class


Class body

The class body follows the class declaration and continues to the next class declaration or the next end-of-file. It defines any (public) methods declared in the class declaration, as well as any private or secret members or methods.

Example:

... end class end of a class declaration
    method pubmeth (integer x) Define a method declared in the class declaration.
    ... end method End of pubmeth().
    method privmeth () define a private method.
    secret method secmeth() define a secret method.
... The body continues to EOF or the next class declaration


inherit

The keyword inherit can only be used within a class declaration where it specifies a previously defined class as an ancestor of the current class.  Multiple inheritance is allowed. Conflicts between like-named members in multiple parents are resolved by chaining the class names in the instance reference. (see examples!)

Example:
class Child  
   inherit Base --Inherit from Base
   inherit Mix --and from Mix!
   ...  
end class  



class

The keyword class begins a class declaration which specifies the name and public features of a class. It is also used after 'end' to terminate the public declaration of the class (but NOT the definition of the class!).

Example:
class Child -- Begin declaration of class 'Child'.
   ...  
end class -- end the declaration and begin the class implementation



member

The keyword member occurs in two contexts. Within a class declaration it both declares and defines a public data member of the class. Following a class declaration, it declares and defines a private (or secret) data member.

Example:
...  
end class --the end of a class declaration
 member integer x -- Define a private data member. A type ('integer' in this case) is meaningless except as documentation but is required.
 secret member sequence s -- the 'secret' prefix hides the member from both descendents and clients



method

The keyword method occurs in two contexts. Within a class declaration it declares a public method of the class. Following a class declaration, it begins the definition of a method which is ended by "end method". The resulting method is public if it was named in the class declaration, secret if the method keyword was preceded by 'secret', otherwise private.

Example:
class SomeClass  
method x -- x is declared in public area.
end class -- the end of the publics (class declaration)
 method x () -- x() is public
method y () -- y() is private -- available only to descendents



secret

The secret keyword is used as a qualifier with the member or method keywords within a class body to hide the member or method from all outsiders. Remember that the private restriction hides the feature from clients but not from descendents.

Example:

secret member integer x -- Hide x from all others



private

private is not a keyword but is the default visibility of members and methods within the class body. Members and methods which are defined in the body but not declared within the declaration become 'private'. They can then be accessed by descendents but not by clients.

Example:
class SomeClass  
method x -- x is declared in public area.
end class -- the end of the publics (class declaration)
 method x () -- x() is public
method y () -- y() is private -- available only to descendents


virtual

The virtual keyword is used in class declarations to declare a function or procedure whose definition will be in a descendent class. This creates what is known as a 'virtual class'. Goo does not prevent the creation of instances of a virtual class like most OO languages, but of course any reference to the virtual function will cause a run-time error. The virtual function may be called from within the class. Demo\poly.goo provides an example of both polymorphisn and the virtual keyword. At the end of a class declaration, all public methods named in the declaration are actually virtual-- the coming class body will provide their definitions, and at the end of the body, any which have not been defined will draw a warning (not an error!). The purpose of 'virtual' is to supress this warning and provide the function/procedure information to the translator.

Example:
class SomeClass  
virtual procedure vp -- vp is a procedure (no return value) which be defined in a child.
virtual function vfct -- declare a virtual function
end class -- the end of the publics
method A() -- a method of SomeClass
   vp() -- can call the future procedure



instance of

The instance of keyword is used to define an instance of a class. The resulting instance has client access privileges to the named class. If the referenced class has a public method named 'initialize' then the class name may be followed by a parameter list, which will be passed to the initialize() function of the instance. The instance is then accessed using dot notation.

Example:
instance x of Base -- Create an instance of class 'Base'
instance y of Base ("test") -- instance y is created and its initialize() function is called



dot notation

Instances are accessed using normal dot-notation. The basic notation is ins.feature where ins is a previously created instance and feature is an accessible member or method of that instance. If feature is a method taking no parameters, then the empty parameter list is optional ('()' not needed). If feature is itself an instance, then the dot-notation may be chained as in ins.feature.fct(). Please note that the parents of a class are themselves features of a class and may be included in the dot-notation. This is the mechanism for selecting from like-named members in multiple parents. Within a method, a feature of the current instance may be referred to as .feature or this.feature. Finally the notation ins. refers to the entire instance, and can be use for copying instances.

Example:
instance X of CLS -- Create an instance
X.cnt = 3 -- set X's cnt member
rslt = X.name() -- call X's 'name' function
rslt = X.name -- call X's 'name' function
X.inst.foo() -- call the 'foo' function in the 'inst' member of XX
X.parent.foo() -- accessing a parents function looks the same
integer y   y = X -- y now refers to the same instance as X
Y. = X. -- copy instance X into instance Y
this.memb -- refer to member 'memb' of the current instance (within a method)
.memb -- shorthand for 'this.memb'



Parameter Instances

Instances may be passed to functions, procedures, or methods as parameters. Instances are actually Euphoria integers which index into a global list of instances (named oo_I). This creates two powerful capabilities: pass-by-reference (the receiving function can modify the passed instance), and a restricted form of polymorphism.

procedure find (instance x of Acls) -- declare a procedure taking an instance parameter
   -- x is used normally within the procedure
instance qq of Acls -- create an instance
find(qq) -- pass it in the obvious way



Local Instances

Instances may be declared as locals in functions or procedures. However, the programmer must mark the end of the locals with the '$$' operator. This is because Euphoria requires local to be at the start of functions or procedures, and it is difficult for the translator to detect the last local. In addition it provides a line where the translator can dump its initialization code. The use of an instance as a parameter does not require this operator. Note that inline initializations (see shorthands) require the same hint.
procedure x () => procedure x () Start a procedure
   instance a of CLS =>    integer a Local instance
   $$ => a = oo_N(2) '$$' required to dump inits


Polymorphism

Goo provides a form of polymorphism. It requires the programmer to insure that all classes participating in a polymorphism have their polymorphic functions in the same relative position (this is not checked by Goo). In most cases this would be accomplished by placing the polymorphic method in a base class, and having all subclasses inherit that base in the same position. The upside of this is that no table searching need be done at run time. See demo\poly for an example of this.