chickadee » objc » define-objc-class

(define-objc-class CLASS SUPERCLASS IVARS . METHODS)syntax

Defines CLASS (a symbol) with superclass SUPERCLASS (a symbol), instance variables IVARS, and methods METHODS. The new classname is imported with define-objc-classes.

SUPERCLASS is looked up for you in the runtime, so it need not be imported.

IVARS is a list of the form ((TYPE NAME) ...), where TYPE is a type qualifier and NAME is a symbol representing the new variable name. Each instance of CLASS will have a separate copy of these variables.

METHODS are method definitions of the form (define-[class-]method RT ARGS . BODY), which are equivalent to calling (objc:define-[class]-method CLASS RT ARGS . BODY) using the current CLASS. These methods are defined in the lexical environment of the surrounding define-objc-class expression. As a simple consequence, you can surround the class definition with a let statement and create "static" variables for the class.

You can also use + as an alias for define-class-method and - for define-method. These correspond to Objective C method definition syntax.

Example:

 (define-objc-class MyPoint NSObject ((DBL x)
                                      (DBL y) 
                                      (slot: closure))
   (define-method ID init
     (print "MyPoint init")
     (@ super init))
   (- DBL getX @x)
   (- DBL getY @y)
   (- ID description
      (sprintf "<MyPoint: (~a, ~a)>" @x @y))

   (- VOID ((move-by-x: DBL a) (y: DBL b))
     (set! @x (+ a @x))
     (ivar-set! self y (+ b (ivar-ref self y))))  ;; more wordy

   (- ID ((init-with-x: DBL a) (y: DBL b))
      (let ((p (@ self init)))
        (@ p move-by-x: a y: b)
        (set! @closure (lambda (msg)
                         (cond ((eq? msg 'initial-x) 
                                (print "MyPoint: initial x was " a))
                               ((eq? msg 'initial-y) 
                                (print "MyPoint: initial y was " b)))))
        p)))

 #;1> (define p (@ (@ MyPoint alloc) init-with-x: 3.4 y: 4.5))
 MyPoint init
 #;2> (@ p move-by-x: 2 y: 3)
 #<objc-instance <MyPoint: (5.4, 7.5)>>
 #;3> ((ivar-ref p closure) 'initial-x)
 MyPoint: initial x was 3.4