Written by: Carl Eastlund (cce at ccs dot neu dot edu)
Keywords: _class_ _object_ _mixin_ _subclass_ _interface_
          _implements_ _inherits_ _inheritance_ _contract_

This software is distributed under a BSD-style license (see license.txt).


To require this module:

(require (planet "" ("cce" "class-utils.plt")))

This provides:

> class-or-iface/c : FlatContract

Accepts classes and interfaces.

> (subclass-or-implements/c class-or-interface) : FlatContract
  class-or-interface : (Or Class Interface)

If class-or-interface is a class, accepts any subclass of it.
If class-or-interface is an interface, accepts any class which implements it.

> (object/c class-or-interface ...) : FlatContract
  class-or-interface : (Or Class Interface)

Accepts any object whose class implements each given interface and is a subclass
of each given class.

> (class/c class-or-interface ...) : FlatContract

Accepts any class which implements each given interface and is a subclass of
each given class.

> (mixin/c [super-c-or-i ...] [arg-contract ...] [sub-c-or-i]) : Contract
  super-c-or-i : (Or Class Interface)
  arg-contract : Contract
  sub-c-or-i : (Or Class Interface)

Accepts any function satisfying these constraints:
The first input must satisfy (class/c super-c-or-i).
The remaining inputs must satisfy each arg-contract respectively.
The output must satisfy (class/c sub-c-or-i) and inherit from the first input.

Example, a mixin for MrEd drawing contexts which inputs a DC class and four
integers, then produces a new DC class implementing the hypothetical interface
  (mixin/c [dc<%>] [integer? integer? integer? integer?] [bounded<%>])])

> (ensure-iface iface<%> mx class%) : subclass of class% implementing iface<%>
  iface<%> : interface
  mx : mixin implementing iface<%>
  class% : class

If class% implements iface<%>, produces class%; otherwise produces (mx class%).

> (send+ obj-expr (method-name arg-expr ...) ...)

Works just like send*, but returns the object as the final value.
Equivalent to:

(let ([the-object obj-expr])
  (begin (send the-object method-name arg-expr ...)

> (send-each obj-list-expr method-name arg-expr ...)

Works like send, mapped over a list of objects.  Equivalent to:

(let ([objs obj-list-expr] [arg arg-expr] ...)
  (for-each (lambda (obj) (send obj method-name arg ...)) objs))