A Class-based Object Oriented Scripting

pnuts.ext.DynamicClass class is plug-in module for class-based OO scripting. The source code is provided in the distribution package. Sample scripts are also in the distribution package.

Class definition

defclass ( className [ , superclass ] )

To define a class, call defclass() function with a class name. When superclass is specified, its subclass is defined. superclass should be a class which is defined with defclass() function. Members and methods of the class can be defined later.

The return value of the function represents a class, which is actually a pnuts.ext.DynamicClass object.

e.g.
Employee = defclass("Employee")
WorkerBee = defclass("WorkerBee", Employee)
WorkerBee.getClass() ==> class pnuts.ext.DynamicClass

This function is defined in oop.pnut

Instantiation

dynamicClass ( [ parameter list ] )

To instantiate a class, call dynamicClass as a function. When some constructors are defined, parameters can be given. Constructors is described later.

e.g.
joe = Employee()

Type checking

instance . instanceOf ( dynamicClass )
bee = WorkerBee()
bee.instanceOf(Employee)    ==> true

Adding and removing attributes

dynamicClass . var ( attributeName [ , dynamicClass or Class ] )
dynamicClass . remove ( attributeName )

To add an attribute to a class which is defined with defclass() function, call var() method with the name of the attribute. When dynamicClass or Class is specified, it is the type of the attribute.

Employee.var("name", String)

Similarly, to remove an attribute, call remove method.

Employee.remove("name")

Users can add and remove attributes at any time in the execution.

Access to attributes

instance . attributeName
instance . attributeName = value

Attributes can be accessed as if they are public memebers of a Java object.

joe = Employee()
joe.name = "Joseph"
joe.name = 123  ==> an exception is thrown
joe.name        ==> "Joseph"

Attributes can be inherited along the class hierarchy.

kevin = WorkerBee()
kevin.name = "Kevin"
kevin.name        ==> "Kevin"

Method definition

dynamicClass . method ( methodName , function ( arg ) block )
dynamicClass . removeMethod ( methodName )

To define a method, call "method()" method for the class which is defined with defclass(). The first parameter of method() should be the method's name. the second parameter is a function which defines the body of the method.

Employee.method("sayhello", function () println("How are you?"))
Employee.method("sayhello", function (who) println("How are you," + who + "?"))

Usually the second parameter is an anonymous function. Anonymous functions are useful because every anonymous function has a unique identifier.

Two variables are predefined in method functions. "this" is the instance itself. "super" can be used to call a method or read a variable of a superclass.

The internal representation of methods is like:
    (function (this, super) method_definition)
         (the_instance, reference_to_super)

Member access in a method definition

To access attributes in a method definition, "this" is required as the target of the access.

e.g.
Employee.var("grade", int)
Employee.method("promote", function () this.grade++)

Constructors

A constructor is just a method with special name "new".

Employee.method("new", function (name) this.name = name)

joe = Employee("Joseph")

Calling methods in an ancester class

To call a method of an ancestor from a method definition, specify the special attribute "super".

e.g.
WorkerBee.method("promote",
                   function (){
                     super.promote()
                     println("thanks")
                   }
                 )

Back