current stable:
0.99.6
unstable:
cvs (0.99.7)
General
  Home / News
  About
  Contact
  The Team

Obtaining
  Download
  Source Tarball
  CVS Web View
  Misc. Files

Documentation
  Introduction
The Manual
  Download [html]
  Download [pdf]
  View Online
API
  Download [html]
  View Online
Resources
  Script Examples

Developer
  Introduction
Developer Guide
  Download [html]
  Download [pdf]
  View Online
Ferite C API
  Download [html]
  View Online




Open Source Approved

SourceForge Logo
KwMap.net - browse the Keyword Map of ferite.org

[previous] Functions[up][toc]Namespaces [next]


Classes and Objects (and references)

A class is a collection of data and methods, where the methods are intended to work on the data. Classes are templates for variables they describe how complex data types work. To use a class it is necessary to create and instance of a class (see the new keyword) and assign it to an object variable. The syntax of a class is as follows:

    class <name of class> {
        <variable and functions declarations>
    }
    				

An example class:

    class foo {
    	string bar;
    
    	function foo( string str ){ // constructor
    		self.bar = str; // make bar equal to passed string
    	}
    
    	function printBar(){
    		Console.println( self.bar ); // print bar
    	}
    }
    				

This defines a class with a string and two methods. To create an instance of this class you would do the following:

    object someObj = new foo( "Hello World" );
    someObj.printBar(); // will output Hello World
    				

To reference variables and methods from within the class it is necessary to prefix the variable with self. or simply a .. This merely tells ferite that you want the variable within the class (it is not necessary to do this for locally scoped variables within methods). The self. is the long notation, but you can leave the self bit out and ferite will work it out :-).

Classes can have constructors, these are within the form of a method with the same name as the class. The constructor will be called implicitly when an instance is created. It is suggested that you place you initialisation code here. (It should be noted that you can use all variables within a class in the constructor as they have already been created for you). An example of a constructor can been see above - method is called foo.

It is possible to extend classes by using inheritance, this is done using the extends keyword. There is no multiple inheritance and an example of inheritance is:

    class Person {
    	string name;
    	number age;
    
    	function Person( string n, number a ){ // constructor
    		self.name = n;
    		self.age = a;
    	}
    }
    
    class Employee extends Person {
    	number salary;
    
    	function Employee( string n, number a, number sal ){ // constructor
    		super.Person( n, a );
    		self.salary = sal;
    		self.name += " - Employee"; // change the name
    	}
    }
    				

These classes are not usable in any fashion but merely highlight inheritance.

A couple of important facts need to be noticed:

  1. When inheritance occurs and then an instance is made, the constructor of the super (parent) class is not called automatically. It is up to the subclass (child) to explicitly call it. This can either be done by doing super.NameOfConstructor() or super(). Either way is the same in the long run.

  2. To get the object as a cast of the super class the super keyword is used. E.g. super.someFunction() will call the function someFunction as if it was coming from an object created from the parent class.

  3. Function overloading works with objects and classes aswell.

Currently there is no support for private or protected members of a class. This is a planned addition in the future. As a general rule of thumb, it is considered bad practice to directly access an objects variables. If they need to be read or modified - methods should be supplied and used.

When an instance of a class is created it is added to the garbage collector so that is can keep an eye on it. Then a reference is returned - this is merely a pointer to the object within the system, this means that if you then assign one object variable to another - they both point to the same object.

Example:

    class foo {
    	string name;
    
    	function foo( string n ){ //constructor
    		self.name = n;
    	}
    }
    
    object objA, objB;
    objA = new foo("boris" );
    objB = objA; // they both now point to the same object foo with name="boris"
    				

Due to this and combined with the garbage collector, objects will automatically get cleaned up and removed from the system when they are not referenced anymore. It should also be noted that the garbage collector does work based on reference counting and is therefore susceptible to circular references. There is no guarantee as to when an object will be destroyed.

Static Members

Ferite supports static members within classes. These act the same as within Java and allow to have functions and variables on a per class basis rather than a per object basis. Static functions and variables are to classes what functions and variables are to namespaces. To reference them you simply use the class name then the member name, e.g. for a static function bar in the class Foo you would call it by doing Foo.bar. If you try and access a static member by using an object (rather than the class) an exception will be thrown.

This is used as follows (both function and variable shown):

    static function_name( parameter declarations ){
    	variable declarations
    	statements
    }
    
    static number nameofvar;
    					

Modifying Existing Classes

ferite has a number of features that allows you to modify existing classes. Why is this useful? Well, say you have a class that is used all over the place, lets say File, and you wish to debug a method, or reimplement a method to work around a bug, or even just add a method. It transparently allows you to shape an existing class to be how you want it to be.

To do this you use two keywords: modifies and rename. Here is an example:

    class modifies File {
    
       rename readln oldReadln;
       rename open oldOpen;
    
       function readln(){
    	  return self.oldReadln(1024);
       }
    
       function open( string file, string mode ){
    	  self.oldOpen( file, mode, "" );
       }
    
       function toString(){
    	  string str = "";
    
    	  while( !self.eof() )
    		str += self.readln();
    	  return str;
       }
    }
    					

To modify a class you use the syntax 'class modifies nameOfClass', this will tell ferite that the target is that class, the class must exist otherwise you will get a compile error. Once this is done you can add new methods and variables, and twiddle with the existing ones.

rename - this takes two labels, the current name and the new name and renames it. The advantage of this approach is that you can drop in a replacement method and still call the old method within your new method. The above example re-implements the .readln method within the File class such that it doesn't require he passing of a number of bytes to read.

The above example also adds a new toString() which will return the file's contents in a string.

WARNING: you can potentially cause alot of confusion using these, but they are very useful for debuging and various other uses. You can modify any class.



[previous] Functions[up][toc]Namespaces [next]
ferite et al © 2000-2004, Chris Ross