a collection of fields;
a collection of methods;
initial value expressions for the fields; and
initialization variables that are bound to initialization arguments.
An object is a collection of bindings for fields that are instantiated according to a class description.
The primary role of the object system is ability to define a new class (a derived class) in terms of an existing class (the superclass) using inheritance and overriding:
inheritance: An object of a derived class supports methods and instantiates fields declared by the derived class's superclass, as well as methods and fields declared in the derived class expression.
overriding: A method declared in a superclass can be redeclared in the derived class. References to the overridden method in the superclass use the implementation in the derived class.
An interface is a collection of method names to be implemented by a class, combined with a derivation requirement. A class implements an interface when it
declares (or inherits) a public method for each variable in the interface;
is derived from the class required by the interface, if any; and
specifically declares its intention to implement the interface.
A class can implement any number of interfaces. A derived class automatically implements any interface that its superclass implements. Each class also implements an implicitly-defined interface that is associated with the class. The implicitly-defined interface contains all of the class's public method namess, and it requires that all other implementations of the interface are derived from the class.
A new interface can extend one or more interfaces with additional method names; each class that implements the extended interface also implements the original interfaces. The derivation requirements of the original interface must be consistent, and the extended interface inherits the most specific derivation requirement from the original interfaces.
Classes, objects, and interfaces are all first-class Scheme values. However, a MzScheme class or interface is not a MzScheme object (i.e., there are no ``meta-classes'' or ``meta-interfaces'').
The following example converys the object system's basic style.
(define stack<%> (interface () push! pop! none?)) (define stack% (class*object%
(stack<%>) ; Declare public methods: (public push! pop! none? print-name) (define stacknull
) ; A private field (init-field (name 'stack)) ; A public field ; Method implementations: (define (push! v) (set! stack (cons
v stack))) (define (pop!) (let ([v (car
stack)]) (set! stack (cdr
stack)) v)) (define (none?) (null?
stack)) (define (print-name) (display
name) (newline
)) ; Call superclass initializer: (super-instantiate ()))) (define fancy-stack% (class stack% ; Declare override (override print-name) ; Add inherited field to local environment (inherit-field name) (define (print-name) (display
name) (display
", Esq.") (newline
)) (super-instantiate ()))) (define double-stack% (class stack% (inherit push!) (public double-push!) (define (double-push! v) (push! v) (push! v)) ; Always supply name (super-instantiate () (name 'double-stack)))) (define-values (make-safe-stack-class is-safe-stack?) (let ([safe-stack<%> (interface (stack<%>))]) (values
(lambda (super%) (class* super% (safe-stack<%>) (inherit none?) (rename [std-pop! pop!]) (override pop!) (define (pop!) (if (none?) #f (std-pop!))) (super-instantiate ()))) (lambda (obj) (is-a?
obj safe-stack<%>))))) (define safe-stack% (make-safe-stack-class stack%))
The interface stack<%>
1 defines the ever-popular stack
interface with the methods push!
, pop!
, and none?
.
Since it has no superinterfaces, the only derivation requirement of
stack<%>
is that its classes are derived from the built-in
empty class, object%
. The class stack%
2 is derived from
object%
and implements the stack<%>
interface. Three
additional classes are derived from the basic stack%
implementation:
The class fancy-stack%
defines a stack that overrides
print-name
to add an ``Esq.'' suffix.
The class double-stack%
extends the functionality
stack%
with a new method, double-push!
. It also
supplies a specific name
to stack%
.
The class safe-stack%
overrides the
pop!
method of stack%
, ensuring that #f
is
returned whenever the stack is empty.
In each derived class, the call (super-instantiate ...)
causes the superclass portion of the object to be initialized,
including the initialization of its fields.
The creation of safe-stack%
illustrates the use of classes as
first-class values. Applying make-safe-stack-class
to
named-stack%
or double-stack%
-- indeed, any
class with push
, pop!
, and none?
methods --
creates a ``safe'' version of the class. A stack object can be
recognized as a safe stack by testing it with is-safe-stack?
;
this predicate returns #t
only for instances of a class
created with make-safe-stack-class
(because only those classes
implement the safe-stack<%>
interface).
In each of the example classes, the field name
contains the
name of the class. The name
instance variable is introduced
as a new instance variable in stack%
, and it is declared
there with the init-field
keyword, which means that an
instantiation of the class can specify the initial value, but it
defaults to 'stack
. The double-stack%
class
provides name
when initializing the stack%
part of
the object, so a name cannot be supplied when instantiating
double-stack%
. When the print-name
method of an
object from double-stack%
is invoked, the name printed to
the screen is always ``double-stack''.
While all of named-stack%
, double-stack%
, and
safe-stack%
inherit the push!
method of
stack%
, it is declared with inherit
only in
double-stack%
; new declarations in named-stack%
and
safe-stack%
do not need to refer to push!
, so the
inheritance does not need to be declared. Similarly, only
safe-stack%
needs to declare (inherit none?)
.
The safe-stack%
class overrides pop!
to extend the
implementation of pop!
. The new definition of pop!
must
access the original pop!
method that is defined in
stack%
. The rename
declaration binds a new name,
std-pop!
to the original pop!
. Then, std-pop!
is
used in the overriding pop!
. Variables declared with
rename
cannot be overridden, so std-pop!
will
always refer to the superclass's pop!
.
The instantiate
form and
procedure both
create an object from a class. The make-object
instantiate
form supports
initialization arguments by both position and name, while
supports initialization arguments by position
only. The following examples create objects using the classes above:
make-object
(define stack (make-object
stack%)) (define fred (make-object
stack% 'Fred)) (define joe (instantiate stack% () (name 'Joe))) (define double-stack (make-object
double-stack%)) (define safe-stack (instantiate safe-stack% () (name 'safe)))
The send
form calls a method on an object, finding the method by
name. The following example uses the objects created above:
(send stack push! fred)
(send stack push! double-stack)
(let loop ()
(if (not
(send stack none?))
(begin
(send (send stack pop!) print-name)
(loop))))
This loop displays 'double-stack
and 'Fred
to the
standard output port.
The interface
form creates a new interface:
(interface (super-interface-expr ···) variable ···)
All of the variable
s must be distinct.
Each super-interface-expr
is evaluated (in order) when the
interface
expression is evaluated. The result of each
super-interface-expr
must be an interface value, otherwise the
exn:object
exception is raised. The interfaces returned by the
super-interface-expr
s are the new interface's superinterfaces,
which are all extended by the new interface. Any class that
implements the new interface also implements all of the
superinterfaces.
The result of an interface
expression is an interface that
includes all of the specified variable
s, plus all variables
from the superinterfaces. Duplicate variable names among the
superinterfaces are ignored, but if a superinteface contains one of
the variable
s in the interface
expression, the
exn:object
exception is raised.
If no super-interface-expr
s are provided, then the derivation
requirement of the resulting interface is trivial: any class that
implements the interface must be derived from object%
.
Otherwise, the implementation requirement of the resulting interface
is the most specific requirement from its superinterfaces. If the
superinterfaces specify inconsistent derivation requirements, the
exn:object
exception is raised.
The built-in class object%
has no methods fields,
implements only its own interface, (
. All other classes are derived from class->interface
object%)object%
.
The class*/names
form creates a new class:
(class*/names local-names superclass-expr (interface-expr ···) class-clause ···) local-names is one of (this-variable) (this-variable super-instantiate-variable) (this-variable super-instantiate-variable super-make-object-variable) class-clause is one of (init init-declaration ···) (init-field init-declaration ···) (field field-declaration ···) (inherit-field variable ···) (init-rest variable) (init-rest) (public optionally-renamed-variable ···) (override optionally-renamed-variable ···) (public-final optionally-renamed-variable ···) (override-final optionally-renamed-variable ···) (private variable ···) (inherit optionally-renamed-variable ···) (rename renamed-variable ···) method-definition definition expr (begin class-clause ···) init-declaration is one of variable (variable default-value-expr) field-declaration is (variable default-value-expr) optionally-renamed-variable is one of variable renamed-variable renamed-variable is (internal-variable external-variable) method-definition is (define-values (variable) method-procedure) method-procedure is (lambda formals expr ···1) (case-lambda (formals expr ···1) ···) (let-values (((variable) method-procedure) ···) method-procedure) (letrec-values (((variable) method-procedure) ···) method-procedure) (let-values (((variable) method-procedure) ···1) variable) (letrec-values (((variable) method-procedure) ···1) variable)
The this-variable
, super-instantiate-variable
, and
super-make-object-variable
variables (usually this
,
super-instantiate
, and super-make-object
) are bound in
the rest of the class*/names
expression, excluding
superclass-expr
and the interface-expr
s. In instances of
the new class, this-variable
(i.e., this
) is
bound to the object itself; super-instantiate-variable
(i.e.,
super-instantiate
) is bound to a form that must be used
(once) to initialize fileds in the superclass (see
section 3.4); super-make-object-variable
(i.e.,
super-make-object
) can be used instead of
super-instantiate-variable
to initialize superclass fields.
See section 3.4 for more information about
super-instantiate-variable
and
super-make-object-variable
.
The superclass-expr
expression is evaluated when the
class*/names
expression is evaluated. The result must be a
class value (possibly object%
), otherwise the
exn:object
exception is raised. The result of the superclass-expr
expression is the new class's superclass.
The interface-expr
expressions are also evaluated when the
class*/names
expression is evaluated, after
superclass-expr
is evaluated. The result of each
interface-expr
must be an interface value, otherwise the
exn:object
exception is raised. The interfaces returned by the
interface-expr
s are all implemented by the class. For each
variable in each interface, the class (or one of its ancestors) must
declare a public instance variable with the same name, otherwise the
exn:object
exception is raised. The class's superclass must satisfy the
implementation requirement of each interface, otherwise the
exn:object
exception is raised.
The class-clause
s define initialization arguments, public and
private fields, and public and private methods. For each
variable
or optionally-renamed-variable
in a
public
, override
, public-final
,
override-final
, or private
clause, there must be
one method-definition
. All other definition
class-clause
s create private fields. All remaining expr
s
are initialization expressions to be evaluated when the class is
instantiated (see section 3.4).
The result of a class*/names
expression is a new class, derived
from the specified superclass and implementing the specified
interfaces. Instances of the class are created with the
instantiate
form or make-object
procedure, as described
in section 3.4.
Each class-clause
is (partially) macro-expanded to reveal its
shapes. If a class-clause
is a begin
expression,
its sub-expressions are lifted out of the begin
and treated
as class-clause
s, in the same way that begin
is
flattened for top-level and embedded definitions.
The class*
form is like class*/names
, but omits
local-names
and always uses the name
,
this
super-instantiate
, and
:
super-make-object
(class* superclass-expr (interface-expr ···) class-clause ···)
The class
form further omits the interface-expr
s,
for the case that none are needed:
(class superclass-expr class-clause ···)
The public*
, override*
, and
private*
forms abbrviate a public
,
override
, or private
declaration and a sequence of
definitions:
(public* (name expr) ···) =expands=> (begin (public name ···) (define name expr) ···) etc.
The define/public
, define/override
, and
define/private
forms similarly abbrviate a
public
, override
, or private
declaration
with a definition:
(define/public name expr) =expands=> (begin (public name) (define name expr)) (define/public (name . formals) expr) =expands=> (begin (public name) (define (name . formals) expr)) etc.
A class's initialization variables, declared with init
,
init-field
, and init-rest
, are instantiated
for each object of a class. Initialization variables can be used in
the initial value expressions of fields, default value expressions
for initialization arguments, and in initialization expressions. Only
initialization variables declared with init-field
can be
accessed from methods; accessing any other initialization variable
from a method is a syntax error.
The values bound to initialization variables are
the arguments provided with instantiate
or passed to
make-object
, if the object is created as a direct instance
of the class; or,
the arguments passed to the superclass initialization form or procedure, if the object is created as an instance of a derived class.
If an initialization argument is not provided for a initalization
variable that has an associated default-value-expr
, then the
default-value-expr
expression is evaluated to obtain a value
for the variable. A default-value-expr
is only evaluated when
an argument is not provided for its variable. The environment of
default-value-expr
includes all of the initialization
variables, all of the fields, and all of the methods of the class. If
multiple default-value-expr
s are evaluated, they are evaluated
from left to right. Object creation and field initialization are
described in detail in section 3.4.
If an initialization variable has no default-value-expr
, then
the object creation or superclass initialization call must supply an
argument for the variable, otherwise the exn:object
exception is raised.
Initialization arguments can be provided by name or by position. The
name of an initialization variable can be used with
instantiate
or with the superclass initialization form. Those
forms also accept by-position arguments. The make-object
procedure and the superclass initialization procedure accept only
by-position arguments.
Arguments provided by position are converted into by-name arguments
using the order of init
and init-field
clauses and
the order of variables within each clause. When a instantiate
form provides both by-position and by-name arguments, the converted
arguments are placed before by-name arguments. (The order can be
significant; see also section 3.4.)
Unless a class contains an init-rest
clause, when the number
of by-position arguments exceeds the number of declared
initialization variables, the order of variables in the superclass
(and so on, up the superclass chain) determines the by-name
conversion.
If a class expression contains an init-rest
clause, there
must be only one, and it must be last. If it declares a variable,
then the variable receives extra by-position initialization arguments
as a list (similar to a dotted ``rest argument'' in a procedure). An
init-rest
variable can receive by-position initialization
arguments that are left over from a by-name conversion for a derived
class. When a derived class's superclass initialization provides even
more by-position arguments, they are prefixed onto the by-position
arguments accumulated so far.
If too few or too many by-position initialization arguments are
provided to an object creation or superclass initialization, then the
exn:object
exception is raised. Similarly, if extra by-position arguments are
provided to a class with an init-rest
clause, the
exn:object
exception is raised.
Unused (by-name) arguments are be propagated to the superclass, as described in section 3.4. Multiple initialization arguments can use the same name if the class derivation contains multiple declarations (in different classes) of initialization variables with the name. See section 3.4 for further details.
Each field
, init-field
, and non-method
define-values
clause in a class declares one or more new
fields for the class. Fields declared with field
or
init-field
are public. Public fields can be access and
mutated by subclasses using inherit-field
. Public fields are
also accessible outside the class via class-field-accessor
and mutable via class-field-mutator
(see
section 3.5). Fields declared with define-values
are
accessible only within the class.
A field declared with init-field
is both a public field an an
initialization variable. See section 3.3.1 for information
about initialization variables.
An inherit-field
declaration makes a public field defined
by a superclass directly accessible in the class expression. If the
indicated field is not defined in the superclass, the
exn:object
exception is raised when the class expression is evaluated. Every
field in a superclass is present in a derived class, even if it is
not declared with inherit-field
in the derived class. The
inherit-field
clause does not control inheritance, but
merely controls lexical scope within a class expression.
When an object is first created, all of its fields have the undefined value (see section 3.1 in PLT MzScheme: Language Manual). The fields of a class are initialized at the same time that the class's initialization expressions are evaluated; see section 3.4 for more information.
Each public
, override
,
public-final
, override-final
, and
private
clause in a class declares one or more method
names. Each method name must have a corresponding
method-definition
. The order of public
,
override
, public-final
, override-final
,
private
clauses and their corresponding definitions (among
themselves, and with respect to other clauses in the class) does not
matter.
As shown in section 3.3, a method definition is syntactically
restricted to certain procedure forms, as defined by the grammar for
method-procedure
; in the last two forms of
method-procedure
, the body variable
must be one of the
variable
s bound by let-values
or
letrec-values
. A method-procedure
expression is not
evalated directly. Instead, for each method, a class-specific method
procedure is created; it takes an initial object argument, in
addition to the arguments the procedure would accept if the
method-procedure
expression were evaluated directly. The
body of the procedure is transformed to access methods and fields
through the object argument.
A method declared with public
or public-final
introduces a new method into a class. The method must not be present
already in the superclass, otherwise the exn:object
exception is raised when
the class expression is evaluated. A method declared with
public-final
cannot be overridden in a subclass.
A method declared with override
or override-final
overrides a definition already present in the superclass. If the
method is not already present, the exn:object
exception is raised when the
class expression is evaluated. A method declared with
override-final
cannot be overridden in a subclass.
A method declared with private
is not accessible outside the
class expression, cannot be overridden, and never overrides a method
in the superclass.
Each inherit
and rename
clause declares one
or more methods that are not defined in the class, but must be
present in the superclass. Methods declared with inherit
are
subject to overriding, while methods declared with rename
are not. Methods that are present in the superclass but not declared
with inherit
or rename
are not directly accessible
in the class (through they can be called with send
).
Every public method in a superclass is present in a derived class,
even if it is not declared with inherit
in the derived
class. The inherit
clause does not control inheritance, but
merely controls lexical scope within a class expression.
If a method declared with inherit
is not present in the
superclass, the exn:object
exception is raised when the class expression is
evaluated.
Each method declared with public
, override
,
public-final
, override-final
, inherit
, and
rename
can have separate internal and external names. The
internal name is used to access the method directly within the class
expression, while the external name is used with send
and
generic
(see section 3.5). If a single
variable
is provided for a method, it is used for both the
internal and external names.
Method inheritance and overriding are based external names, only.
Separate internal and external names are required for
rename
, because its purpose is to provide access to the
superclass's version of an overridden method.
An init variable or field declared with init
, field
,
or init-field
uses the same name internally and
externally.3 An init variable name is used externally as a
keyword for initialize
, and a field name is used externally
in creating field accessors and mutators with
class-field-accessor
and class-field-mutator
.
A single identifier can be used as an internal variable and an external variable, and it is possible to use the same identifier as internal and external variables for different bindings (as long as all internal variables are distinct and all external variables are distinct).
By default, external names have no lexical scope, which means, for
example, that an external method name matches the same syntactic
symbol in all uses of send
. The
define-local-member-name
form introduces a set of scoped
external names:
(define-local-member-name variable ···)
This form binds each variable
so that, within the scope of the
definition, each use of each variable
as an external name is
resolved to a hidden name generated by the
define-local-member-name
declaration. Thus, methods and fields
declared with such external-name variable
s are accessible only
in the scope of the define-local-member-name
declaration.
The binding introduced by define-local-member-name
is a syntax
binding that can be exported and imported with modules (see
section 5 in PLT MzScheme: Language Manual). Each execution of a
define-local-member-name
declaration generates a distinct
hidden name. The interface->method-names
procedure (see
section 3.6) does not expose hidden names.
Example:
(define o (let () (define-local-member-name m) (define c% (classobject%
(define/public (m) 10) (super-make-object
)) (define o (make-object
c%)) (send o m) ; =>10
o)) (send o m) ; => error: no methodm
The make-object
procedure creates a new object with by-position
initialization arguments:
(make-object
class init-v
···)
An instance of class
is created, and the init-v
s are
passed as initialization arguments, bound to the initialization
variables of class
for the newly created object as described in
section 3.3.1. If class
is not a class, the
exn:application:type
exception is raised.
The instantiate
form creates a new object with both
by-position and by-name initialization arguments:
(instantiate class-expr (by-pos-expr ···) (variable by-name-expr) ···)
An instance of the value of class-expr
is created, and the
values of the by-pos-expr
s are provided as by-position
initialization arguments. In addition, the value of each
by-name-expr
is provided as a by-name argument for the
corresponding variable
.
All fields in the newly created object are initially bound to the
special undefined value (see
section 3.1 in PLT MzScheme: Language Manual). Initialization variables with default value
expressions (and no provided value) are also initialized to
undefined. After argument values are assigned to initialization
variables, expressions in field
clauses, init-field
clauses with no provided argument, init
clauses with no
provided argument, private field definitions, and other expressions
are evaluated. Those expressions are evaluated as they appear in the
class expression, from left to right.
Sometime during the evaluation of the expressions, superclass-declared
initializations must be executed once by invoking the form bound to
super-instantiate-variable
(usually
super-instantiate
):
(super-instantiate-variable (by-position-super-init-expr ···) (variable by-name-super-init-expr ···) ···)
or by calling the procedure bound to super-make-object-variable
(usually
):
super-make-object
(super-make-object-variable super-init-v ···)
The by-position-super-init-expr
s,
by-name-super-init-exp
s, and super-init-v
s are mapped to
initialization variables in the same way as for
instantiate
and
.make-object
By-name initialization arguments to a class that have no matching
initialization variable are implicitly added as by-name arguments to
a super-instantiate-variable
or
super-make-object-variable
invocation, after the explicit
arguments. If multiple initialization arguments are provided for the
same name, the first (if any) is used, and the unused arguments are
propagated to the superclass. (Note that converted by-position
arguments are always placed before explicit by-name arguments.) The
initialization procedure for the object%
class accepts zero
initialization arguments; if it receives any by-name initialization
arguments, then exn:object
exception is raised.
Fields inherited from a superclass will not be initialized until the superclass's initialization procedure is invoked. In contrast, all methods are available for an object as soon as the object is created; the overriding of methods is not affect by initialization (unlike objects in C++).
It is an error to reach the end of initialization for any class in the
hierarchy without invoking superclasses initialization; the
exn:object
exception is raised in such a case. Also, if superclass
initialization is invoked more than once, the exn:object
exception is raised.
In expressions within a class definition, the initialization
variables, fields, and methods of the class all part of the
environment, as are the names bound to
super-instantiate-variable
and
super-make-object-variable
. Within a method body, only the
fields and other methods of the class can be referenced; a reference
to any other class-introduced identifier is a syntax error.
Elsewhere within the class, all class-introduced identifiers are
available, and fields and initialization variables can be mutated
with set!
.
Method names within a class can only be used in the procedure position of an application expression; any other use is a syntax error. To allow methods to be applied to lists of arguments, a method application can have the form
(method-variable arg-expr ··· . arg-list-expr)
which calls the method in a way analogous to (
. The
apply
method-variable arg-expr ··· arg-list-expr)arg-list-expr
must not be a parenthesized expression, otherwise
the dot and the parentheses will cancel each other.
Methods are called from outisde a class with the send
and send/apply
forms:
(send obj-expr method-name arg-expr ···) (send obj-expr method-name arg-expr ··· . arg-list-expr) (send/apply obj-expr method-name arg-expr ··· arg-list-expr)
where the last two forms apply the method to a list of argument
values; in the second form, arg-list-expr
cannot be a
parenthesized expression. For any send
or send/apply
,
if obj-expr
does not produce an object, the
exn:application:type
exception is raised. If the object has no public method
method-name
, the exn:object
exception is raised.
The send*
form calls multiple methods of an object in the
specified order:
(send* obj-expr msg ···) msg is one of (method-name arg-expr ···) (method-name arg-expr ··· . arg-list-expr)
where arg-list-expr
is not a parenthesized expression.
Example:
(send* edit (begin-edit-sequence) (insert "Hello") (insert #\newline) (end-edit-sequence))
which is the same as
(let ([o edit]) (send o begin-edit-sequence) (send o insert "Hello") (send o insert #\newline) (send o end-edit-sequence))
The with-method
form extracts a method from an object and
binds a local name that can be applied directly (in the same way as
declared methods within a class):
(with-method ((variable (object-expr method-name)) ···) expr ···1)
Example:
(let ([s (make-object
stack%)])
(with-method ([push (s push!)]
[pop (s pop!)])
(push 10)
(push 9)
(pop)))
which is the same as
(let ([s (make-object
stack%)])
(send s push! 10)
(send s push! 9)
(send s pop!))
Fields are accessed from outside an object through a field accessor or
mutator procedure produced by class-field-accessor
or
class-field-mutator
:
(class-field-accessor class-expr field-name)
returns
an accessor procedure that takes an instance of the class produced by
class-expr
and returns the value of the object's
field-name
field.
(class-field-mutator class-expr field-name)
returns an
mutator procedure that takes an instance of the class produced by
class-expr
and a new value for the field, mutates the field in
the object named by field-name
, then returns void.
A generic can be used instead of a method name to avoid the
cost of relocating a method by name within a class. The
make-generic
procedure and generic
form create
generics:
(make-generic
class-or-interface symbol
)
returns a generic
that works on instances of class-or-interface
(or an instance
of a class/interface derived from class-or-interface
) to call
the method named by symbol
.
If class-or-interface
does not contain a method with the
(external and non-scoped) name symbol
, the
exn:object
exception is raised.
(generic class-or-interface-expr name)
is analogous to
(make-generic
,
except that class-or-interface-expr
'name
)name
can be a scoped method name declared by
define-local-member-name
(see section 3.3.3.3).
A generic is applied with send-generic
:
(send-generic obj-expr generic-expr arg-expr ···) (send-generic obj-expr generic-expr arg-expr ··· . arg-list-expr)
where the value of obj-expr
is an object and the value of
generic-expr
is a generic.
(object?
v
)
returns #t
if v
is a object, #f
otherwise.
(class?
v
)
returns #t
if v
is a class, #f
otherwise.
(interface?
v
)
returns #t
if v
is an interface,
#f
otherwise.
(class->interface
class
)
returns the interface implicitly defined
by class
.
(object-interface
object
)
returns the interface implicitly
defined by the class of object
.
(is-a?
v interface
)
returns #t
if v
is an instance
of a class that implements interface
, #f
otherwise.
(is-a?
v class
)
returns #t
if v
is an instance of
class
(or of a class derived from class
), #f
otherwise.
(subclass?
v class
)
returns #t
if v
is a class
derived from (or equal to) class
, #f
otherwise.
(implementation?
v interface
)
returns #t
if v
is a
class that implements interface
, #f
otherwise.
(interface-extension?
v interface
)
returns #t
if v
is an interface that extends interface
, #f
otherwise.
(method-in-interface?
symbol interface
)
returns #t
if
interface
(or any of its ancestor interfaces) defines an
instance variable with the name symbol
, #f
otherwise.
(interface->method-names
interface
)
returns a list of symbols for
the instance variable names in interface
(including instance
variables inherited from superinterfaces).