Node:Defining new classes, Next:Anonymous classes, Previous:Field operations, Up:Objects Classes and Modules
Kawa provides various mechanisms for defining new classes.
The define-class
and define-simple-class
forms
will usually be the preferred mechanisms. They have basically
the same syntax, but have a couple of differences.
define-class
allows multiple inheritance as well as true nested
(first-class) class objects. However, the implementation
is more complex: code using it is slightly slower, and the mapping to
Java classes is a little less obvious. (Each Scheme class is implemented
as a pair of an interface and an implementation class.)
A class defined by define-simple-class
is slightly more
efficient, and it is easier to access it from Java code.
The syntax of define-class
are mostly compatible with that
in the Guile and Stk dialects of Scheme.
An implementation restriction is that you should only use
define-class
and define-simple-class
in compiled code.
The problem involves Java class loaders.
define-class name (supers ...) field-or-method-decl ... | Syntax |
define-simple-class name (supers ...) field-or-method-decl ... | Syntax |
field-or-method = field-decl | method-decl field-decl = (fname [:: ftype] [option-keyword option-value]*) method-decl = ((method-name formal-arguments) [:: rtype] body)Defines a new class named name. If define-simple-class is
used, creates a normal Java class named name in the current package.
(If name has the form <xyx> the Java implementation
type is named xyz .) If define-class the implementation is
unspecified. In most cases, the compiler creates a class pair,
consisting of a Java interface and a Java implementation class.
The class inherits from the classes and interfaces listed in supers.
This is a list of names of classes that are in scope (perhaps imported
using Each field-decl declares a public instance "slot" (field) with the given fname. If ftype is specified it is the type of the slot. The following option-keywords are implemented:
Each method-decl declares a public non-static method,
whose name is method-name. (If method-name is not a valid
Java method name, it is mapped to something reasonable.
For example The scope of the body of a method includes the field-decls of the object. It does include the surrounding lexical scope. It sort-of also includes the declared methods, but this is not working yet. |
A simple example:
(define-simple-class <2d-vector> () (x type: <double> init-value: 0.0 init-keyword: x:) (y type: <double> init-value: 0.0 init-keyword: y:) ((add (other :: <2d-vector>)) :: <2d-vector> ;; Kawa compiles this using primitive Java types! (make <2d-vector> x: (+ x (slot-ref other 'x)) y: (+ y (slot-ref other 'y)))) ((scale (factor :: <double>)) :: <2d-vector> ;; Unfortunately, multiply is not yet optimized as addition is. (make <2d-vector> x: (* factor x) y: (* factor y)))) (define-simple-class <3d-vector> (<2d-vector>) (z type: <double> init-value: 0.0 init-keyword: z:) ((scale (factor :: <double>)) :: <2d-vector> ;; Note we cannot override the return type to <3d-vector> ;; because Java does not allow that. Should hide that. . (make <3d-vector> ;; Unfortunately, slot names of inherited classes are not visible. ;; Until this is fixed, use slot-ref. x: (* factor (slot-ref (this) 'x)) y: (* factor (slot-ref (this) 'y)) z: (* factor z))))