mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-22 07:09:54 +00:00
1875 lines
65 KiB
Plaintext
1875 lines
65 KiB
Plaintext
\input texinfo
|
|
@setfilename ../../info/eieio.info
|
|
@set TITLE Enhanced Implementation of Emacs Interpreted Objects
|
|
@set AUTHOR Eric M. Ludlam
|
|
@settitle @value{TITLE}
|
|
@include docstyle.texi
|
|
|
|
@c *************************************************************************
|
|
@c @ Header
|
|
@c *************************************************************************
|
|
|
|
@copying
|
|
This manual documents EIEIO, an object framework for Emacs Lisp.
|
|
|
|
Copyright @copyright{} 2007--2024 Free Software Foundation, Inc.
|
|
|
|
@quotation
|
|
Permission is granted to copy, distribute and/or modify this document
|
|
under the terms of the GNU Free Documentation License, Version 1.3 or
|
|
any later version published by the Free Software Foundation; with no
|
|
Invariant Sections, with the Front-Cover Texts being ``A GNU Manual,''
|
|
and with the Back-Cover Texts as in (a) below. A copy of the license
|
|
is included in the section entitled ``GNU Free Documentation License.''
|
|
|
|
(a) The FSF's Back-Cover Text is: ``You have the freedom to copy and
|
|
modify this GNU manual.''
|
|
@end quotation
|
|
@end copying
|
|
|
|
@dircategory Emacs misc features
|
|
@direntry
|
|
* EIEIO: (eieio). An objects system for Emacs Lisp.
|
|
@end direntry
|
|
|
|
@titlepage
|
|
@center @titlefont{@value{TITLE}}
|
|
@sp 4
|
|
@center by @value{AUTHOR}
|
|
@page
|
|
@vskip 0pt plus 1filll
|
|
@insertcopying
|
|
@end titlepage
|
|
|
|
@macro eieio{}
|
|
@i{EIEIO}
|
|
@end macro
|
|
|
|
@node Top
|
|
@top EIEIO
|
|
|
|
@eieio{} (``Enhanced Implementation of Emacs Interpreted Objects'')
|
|
provides an Object Oriented layer for Emacs Lisp, following the basic
|
|
concepts of the Common Lisp Object System (CLOS). It provides a
|
|
framework for writing object-oriented applications in Emacs.
|
|
|
|
@ifnottex
|
|
@insertcopying
|
|
@end ifnottex
|
|
|
|
@menu
|
|
* Quick Start:: Quick start for EIEIO.
|
|
* Introduction:: Why use @eieio{}? Basic overview, samples list.
|
|
* Building Classes:: How to write new class structures.
|
|
* Making New Objects:: How to construct new objects.
|
|
* Accessing Slots:: How to access a slot.
|
|
* Writing Methods:: How to write a method.
|
|
* Method Invocation:: How methods are invoked.
|
|
* Predicates:: Class-p, Object-p, etc-p.
|
|
* Association Lists:: List of objects as association lists.
|
|
* Customizing:: Customizing objects.
|
|
* Introspection:: Looking inside a class.
|
|
* Base Classes:: Additional classes you can inherit from.
|
|
* Browsing:: Browsing your class lists.
|
|
* Class Values:: Displaying information about a class or object.
|
|
* Default Superclass:: The root superclasses.
|
|
* Signals:: When you make errors.
|
|
* Naming Conventions:: Name your objects in an Emacs friendly way.
|
|
* CLOS compatibility:: What are the differences?
|
|
* Wish List:: Things about EIEIO that could be improved.
|
|
* GNU Free Documentation License:: The license for this documentation.
|
|
* Function Index::
|
|
@end menu
|
|
|
|
@node Quick Start
|
|
@chapter Quick Start
|
|
|
|
@eieio{} provides an Object Oriented layer for Emacs Lisp. You can
|
|
use @eieio{} to create classes, methods for those classes, and
|
|
instances of classes.
|
|
|
|
Here is a simple example of a class named @code{person}, containing
|
|
three slots named @code{name}, @code{birthday}, and @code{phone}:
|
|
|
|
@example
|
|
(defclass person () ; No superclasses
|
|
((name :initarg :name
|
|
:initform ""
|
|
:type string
|
|
:custom string
|
|
:documentation "The name of a person.")
|
|
(birthday :initarg :birthday
|
|
:initform "Jan 1, 1970"
|
|
:custom string
|
|
:type string
|
|
:documentation "The person's birthday.")
|
|
(phone :initarg :phone
|
|
:initform ""
|
|
:documentation "Phone number."))
|
|
"A class for tracking people I know.")
|
|
@end example
|
|
|
|
Each class can have methods, which are defined like this:
|
|
|
|
@example
|
|
(cl-defmethod call-person ((pers person) &optional scriptname)
|
|
"Dial the phone for the person PERS.
|
|
Execute the program SCRIPTNAME to dial the phone."
|
|
(message "Dialing the phone for %s" (slot-value pers 'name))
|
|
(shell-command (concat (or scriptname "dialphone.sh")
|
|
" "
|
|
(slot-value pers 'phone))))
|
|
@end example
|
|
|
|
@noindent
|
|
In this example, the first argument to @code{call-person} is a list,
|
|
of the form (@var{varname} @var{classname}). @var{varname} is the
|
|
name of the variable used for the first argument; @var{classname} is
|
|
the name of the class that is expected as the first argument for this
|
|
method.
|
|
|
|
@eieio{} dispatches methods based on the type of the first argument.
|
|
You can have multiple methods with the same name for different classes
|
|
of object. When the @code{call-person} method is called, the first
|
|
argument is examined to determine the class of that argument, and the
|
|
method matching the input type is then executed.
|
|
|
|
Once the behavior of a class is defined, you can create a new
|
|
object of type @code{person}. Objects are created by calling the
|
|
constructor. The constructor is a function with the same name as your
|
|
class which returns a new instance of that class. Here is an example:
|
|
|
|
@example
|
|
(setq pers (person :name "Eric" :birthday "June" :phone "555-5555"))
|
|
@end example
|
|
|
|
@noindent
|
|
For backward compatibility reasons, the first argument can be a string (a name
|
|
given to this instance). Each instance used to be given a name, so different
|
|
instances could be easily distinguished when debugging.
|
|
|
|
It can be a bit repetitive to also have a :name slot. To avoid doing
|
|
this, it is sometimes handy to use the base class @code{eieio-named}.
|
|
@xref{eieio-named}.
|
|
|
|
Calling methods on an object is a lot like calling any function. The
|
|
first argument should be an object of a class which has had this
|
|
method defined for it. In this example it would look like this:
|
|
|
|
@example
|
|
(call-person pers)
|
|
@end example
|
|
|
|
@noindent
|
|
or
|
|
|
|
@example
|
|
(call-person pers "my-call-script")
|
|
@end example
|
|
|
|
In these examples, @eieio{} automatically examines the class of
|
|
@code{pers}, and ensures that the method defined above is called. If
|
|
@code{pers} is some other class lacking a @code{call-person} method, or
|
|
some other data type, Emacs signals a @code{cl-no-applicable-method}
|
|
error. @ref{Signals}.
|
|
|
|
@node Introduction
|
|
@chapter Introduction
|
|
|
|
First off, please note that this manual cannot serve as a complete
|
|
introduction to object oriented programming and generic functions in
|
|
LISP@. Although EIEIO is not a complete implementation of the Common
|
|
Lisp Object System (CLOS) and also differs from it in several aspects,
|
|
it follows the same basic concepts. Therefore, it is highly
|
|
recommended to learn those from a textbook or tutorial first,
|
|
especially if you only know OOP from languages like C++ or Java. If
|
|
on the other hand you are already familiar with CLOS, you should be
|
|
aware that @eieio{} does not implement the full CLOS specification and
|
|
also differs in some other aspects which are mentioned below (also
|
|
@pxref{CLOS compatibility}).
|
|
|
|
@eieio{} supports the following features:
|
|
|
|
@enumerate
|
|
@item
|
|
A structured framework for the creation of basic classes with attributes
|
|
and methods using inheritance similar to CLOS.
|
|
@item
|
|
Type checking, and slot unbinding.
|
|
@item
|
|
Method definitions similar to CLOS.
|
|
@item
|
|
Simple and complex class browsers.
|
|
@item
|
|
Edebug support for methods.
|
|
@item
|
|
Imenu updates.
|
|
@item
|
|
Byte compilation support of methods.
|
|
@item
|
|
Help system extensions for classes and methods.
|
|
@item
|
|
Several base classes for interesting tasks.
|
|
@item
|
|
Simple test suite.
|
|
@item
|
|
Public and private classifications for slots (extensions to CLOS)
|
|
@item
|
|
Customization support in a class (extension to CLOS)
|
|
@end enumerate
|
|
|
|
Due to restrictions in the Emacs Lisp language, CLOS cannot be
|
|
completely supported, and a few functions have been added in place of
|
|
setf. Here are some important CLOS features that @eieio{} presently
|
|
lacks:
|
|
|
|
@table @asis
|
|
|
|
@item Support for metaclasses
|
|
There is just one default metaclass, @code{eieio-default-superclass},
|
|
and you cannot define your own. The @code{:metaclass} tag in
|
|
@code{defclass} is ignored. Also, functions like @code{find-class}, which
|
|
should return instances of the metaclass, behave differently in
|
|
@eieio{} in that they return symbols or plain structures instead.
|
|
|
|
@item EQL specialization
|
|
EIEIO does not support it.
|
|
|
|
@item @code{:around} method tag
|
|
This CLOS method tag is non-functional.
|
|
|
|
@item :default-initargs in @code{defclass}
|
|
Each slot can have an @code{:initform} tag, so this is not really necessary.
|
|
|
|
@item Mock object initializers
|
|
Each class contains a mock object used for fast initialization of
|
|
instantiated objects. Using functions with side effects on object slot
|
|
values can potentially cause modifications in the mock object. @eieio{}
|
|
should use a deep copy but currently does not.
|
|
|
|
@end table
|
|
|
|
@node Building Classes
|
|
@chapter Building Classes
|
|
|
|
A @dfn{class} is a definition for organizing data and methods
|
|
together. An @eieio{} class has structures similar to the classes
|
|
found in other object-oriented (OO) languages.
|
|
|
|
To create a new class, use the @code{defclass} macro:
|
|
|
|
@defmac defclass class-name superclass-list slot-list &rest options-and-doc
|
|
|
|
Create a new class named @var{class-name}. The class is represented
|
|
by a symbol with the name @var{class-name}. @eieio{} stores the structure of
|
|
the class as a symbol property of @var{class-name} (@pxref{Symbol
|
|
Components,,,elisp,GNU Emacs Lisp Reference Manual}).
|
|
|
|
When defining a class, @eieio{} overwrites any preexisting variable or
|
|
function bindings for the symbol @var{class-name}, which may lead to
|
|
undesired consequences. Before naming a new class, you should check
|
|
for name conflicts. To help avoid cross-package conflicts you should
|
|
choose a name with the same prefix you chose for the rest of your
|
|
package's functions and variables (@pxref{Coding
|
|
Conventions,,,elisp,GNU Emacs Lisp Reference Manual}).
|
|
|
|
The @var{class-name} symbol's variable documentation string is a
|
|
modified version of the doc string found in @var{options-and-doc}.
|
|
Each time a method is defined, the symbol's documentation string is
|
|
updated to include the method's documentation as well.
|
|
|
|
The parent classes for @var{class-name} is @var{superclass-list}.
|
|
Each element of @var{superclass-list} must be a class. These classes
|
|
are the parents of the class being created. Every slot that appears
|
|
in each parent class is replicated in the new class.
|
|
|
|
If two parents share the same slot name, the parent which appears in
|
|
the @var{superclass-list} first sets the tags for that slot. If the
|
|
new class has a slot with the same name as the parent, the new slot
|
|
overrides the parent's slot.
|
|
|
|
When overriding a slot, some slot attributes cannot be overridden
|
|
because they break basic OO rules. You cannot override @code{:type}
|
|
or @code{:protection}.
|
|
@end defmac
|
|
|
|
@noindent
|
|
Whenever defclass is used to create a new class, a predicate is
|
|
created for it, named @code{@var{CLASS-NAME}-p}:
|
|
|
|
@defun CLASS-NAME-p object
|
|
Return non-@code{nil} if and only if @var{OBJECT} is of the class
|
|
@var{CLASS-NAME}.
|
|
@end defun
|
|
|
|
@defvar eieio-error-unsupported-class-tags
|
|
If non-@code{nil}, @code{defclass} signals an error if a tag in a slot
|
|
specifier is unsupported.
|
|
|
|
This option is here to support programs written with older versions of
|
|
@eieio{}, which did not produce such errors.
|
|
@end defvar
|
|
|
|
@menu
|
|
* Inheritance:: How to specify parents classes.
|
|
* Slot Options:: How to specify features of a slot.
|
|
* Class Options:: How to specify features for this class.
|
|
@end menu
|
|
|
|
@node Inheritance
|
|
@section Inheritance
|
|
|
|
@dfn{Inheritance} is a basic feature of an object-oriented language.
|
|
In @eieio{}, a defined class specifies the super classes from which it
|
|
inherits by using the second argument to @code{defclass}. Here is an
|
|
example:
|
|
|
|
@example
|
|
(defclass my-baseclass ()
|
|
((slot-A :initarg :slot-A)
|
|
(slot-B :initarg :slot-B))
|
|
"My Baseclass.")
|
|
@end example
|
|
|
|
@noindent
|
|
To subclass from @code{my-baseclass}, we specify it in the superclass
|
|
list:
|
|
|
|
@example
|
|
(defclass my-subclass (my-baseclass)
|
|
((specific-slot-A :initarg specific-slot-A)
|
|
)
|
|
"My subclass of my-baseclass")
|
|
@end example
|
|
|
|
@indent
|
|
Instances of @code{my-subclass} will inherit @code{slot-A} and
|
|
@code{slot-B}, in addition to having @code{specific-slot-A} from the
|
|
declaration of @code{my-subclass}.
|
|
|
|
@eieio{} also supports multiple inheritance. Suppose we define a
|
|
second baseclass, perhaps an ``interface'' class, like this:
|
|
|
|
@example
|
|
(defclass my-interface ()
|
|
((interface-slot :initarg :interface-slot))
|
|
"An interface to special behavior."
|
|
:abstract t)
|
|
@end example
|
|
|
|
@noindent
|
|
The interface class defines a special @code{interface-slot}, and also
|
|
specifies itself as abstract. Abstract classes cannot be
|
|
instantiated. It is not required to make interfaces abstract, but it
|
|
is a good programming practice.
|
|
|
|
We can now modify our definition of @code{my-subclass} to use this
|
|
interface class, together with our original base class:
|
|
|
|
@example
|
|
(defclass my-subclass (my-baseclass my-interface)
|
|
((specific-slot-A :initarg specific-slot-A)
|
|
)
|
|
"My subclass of my-baseclass")
|
|
@end example
|
|
|
|
@noindent
|
|
With this, @code{my-subclass} also has @code{interface-slot}.
|
|
|
|
If @code{my-baseclass} and @code{my-interface} had slots with the same
|
|
name, then the superclass showing up in the list first defines the
|
|
slot attributes.
|
|
|
|
Inheritance in @eieio{} is more than just combining different slots.
|
|
It is also important in method invocation. @ref{Methods}.
|
|
|
|
If a method is called on an instance of @code{my-subclass}, and that
|
|
method only has an implementation on @code{my-baseclass}, or perhaps
|
|
@code{my-interface}, then the implementation for the baseclass is
|
|
called.
|
|
|
|
If there is a method implementation for @code{my-subclass}, and
|
|
another in @code{my-baseclass}, the implementation for
|
|
@code{my-subclass} can call up to the superclass as well.
|
|
|
|
@node Slot Options
|
|
@section Slot Options
|
|
|
|
The @var{slot-list} argument to @code{defclass} is a list of elements
|
|
where each element defines one slot. Each slot is a list of the form
|
|
|
|
@example
|
|
(SLOT-NAME :TAG1 ATTRIB-VALUE1
|
|
:TAG2 ATTRIB-VALUE2
|
|
:TAGN ATTRIB-VALUEN)
|
|
@end example
|
|
|
|
@noindent
|
|
where @var{SLOT-NAME} is a symbol that will be used to refer to the
|
|
slot. @var{:TAG} is a symbol that describes a feature to be set
|
|
on the slot. @var{ATTRIB-VALUE} is a lisp expression that will be
|
|
used for @var{:TAG}.
|
|
|
|
Valid tags are:
|
|
|
|
@table @code
|
|
@item :initarg
|
|
A symbol that can be used in the argument list of the constructor to
|
|
specify a value for this slot of the new instance being created.
|
|
|
|
A good symbol to use for initarg is one that starts with a colon @code{:}.
|
|
|
|
The slot specified like this:
|
|
@example
|
|
(myslot :initarg :myslot)
|
|
@end example
|
|
could then be initialized to the number 1 like this:
|
|
@example
|
|
(myobject :myslot 1)
|
|
@end example
|
|
|
|
@xref{Making New Objects}.
|
|
|
|
@item :initform
|
|
An expression used as the default value for this slot.
|
|
|
|
If @code{:initform} is left out, that slot defaults to being unbound.
|
|
It is an error to reference an unbound slot, so if you need
|
|
slots to always be in a bound state, you should always use an
|
|
@code{:initform} specifier.
|
|
|
|
Use @code{slot-boundp} to test if a slot is unbound
|
|
(@pxref{Predicates}). Use @code{slot-makeunbound} to set a slot to
|
|
being unbound after giving it a value (@pxref{Accessing Slots}).
|
|
|
|
The value passed to initform used to be automatically quoted. Thus,
|
|
@example
|
|
:initform (1 2 3)
|
|
@end example
|
|
will use the list as a value. This is incompatible with CLOS (which would
|
|
signal an error since 1 is not a valid function) and will likely change in the
|
|
future, so better quote your initforms if they're just values.
|
|
|
|
@item :type
|
|
An unquoted type specifier used to validate data set into this slot.
|
|
@xref{Type Predicates,,,cl,Common Lisp Extensions}.
|
|
Here are some examples:
|
|
@table @code
|
|
@item symbol
|
|
A symbol.
|
|
@item number
|
|
A number type
|
|
@item my-class-name
|
|
An object of your class type.
|
|
@item (or null symbol)
|
|
A symbol, or @code{nil}.
|
|
@end table
|
|
|
|
@item :allocation
|
|
Either :class or :instance (defaults to :instance) used to
|
|
specify how data is stored. Slots stored per instance have unique
|
|
values for each object. Slots stored per class have shared values for
|
|
each object. If one object changes a :class allocated slot, then all
|
|
objects for that class gain the new value.
|
|
|
|
@item :documentation
|
|
Documentation detailing the use of this slot. This documentation is
|
|
exposed when the user describes a class, and during customization of an
|
|
object.
|
|
|
|
@item :accessor
|
|
Name of a generic function which can be used to fetch the value of this slot.
|
|
You can call this function later on your object and retrieve the value
|
|
of the slot.
|
|
|
|
This option is in the CLOS spec, but is not fully compliant in @eieio{}.
|
|
|
|
@item :writer
|
|
Name of a generic function which will write this slot.
|
|
|
|
This option is in the CLOS spec, but is not fully compliant in @eieio{}.
|
|
|
|
@item :reader
|
|
Name of a generic function which will read this slot.
|
|
|
|
This option is in the CLOS spec, but is not fully compliant in @eieio{}.
|
|
|
|
@item :custom
|
|
A custom :type specifier used when editing an object of this type.
|
|
See documentation for @code{defcustom} for details. This specifier is
|
|
equivalent to the :type spec of a @code{defcustom} call.
|
|
|
|
This option is specific to Emacs, and is not in the CLOS spec.
|
|
|
|
@item :label
|
|
When customizing an object, the value of :label will be used instead
|
|
of the slot name. This enables better descriptions of the data than
|
|
would usually be afforded.
|
|
|
|
This option is specific to Emacs, and is not in the CLOS spec.
|
|
|
|
@item :group
|
|
Similar to @code{defcustom}'s :group command, this organizes different
|
|
slots in an object into groups. When customizing an object, only the
|
|
slots belonging to a specific group need be worked with, simplifying the
|
|
size of the display.
|
|
|
|
This option is specific to Emacs, and is not in the CLOS spec.
|
|
|
|
@item :printer
|
|
This routine takes a symbol which is a function name. The function
|
|
should accept one argument. The argument is the value from the slot
|
|
to be printed. The function in @code{object-write} will write the
|
|
slot value out to a printable form on @code{standard-output}.
|
|
|
|
The output format MUST be something that could in turn be interpreted
|
|
with @code{read} such that the object can be brought back in from the
|
|
output stream. Thus, if you wanted to output a symbol, you would need
|
|
to quote the symbol. If you wanted to run a function on load, you
|
|
can output the code to do the construction of the value.
|
|
|
|
@item :protection
|
|
This is an old option that is not supported any more.
|
|
|
|
When using a slot referencing function such as @code{slot-value}, and
|
|
the value behind @var{slot} is private or protected, then the current
|
|
scope of operation must be within a method of the calling object.
|
|
|
|
This protection is not enforced by the code any more, so it's only useful
|
|
as documentation.
|
|
|
|
Valid values are:
|
|
|
|
@table @code
|
|
@item :public
|
|
Access this slot from any scope.
|
|
@item :protected
|
|
Access this slot only from methods of the same class or a child class.
|
|
@item :private
|
|
Access this slot only from methods of the same class.
|
|
@end table
|
|
|
|
This option is specific to Emacs, and is not in the CLOS spec.
|
|
|
|
@end table
|
|
|
|
@node Class Options
|
|
@section Class Options
|
|
|
|
In the @var{options-and-doc} arguments to @code{defclass}, the
|
|
following class options may be specified:
|
|
|
|
@table @code
|
|
@item :documentation
|
|
A documentation string for this class.
|
|
|
|
If an Emacs-style documentation string is also provided, then this
|
|
option is ignored. An Emacs-style documentation string is not
|
|
prefixed by the @code{:documentation} tag, and appears after the list
|
|
of slots, and before the options.
|
|
|
|
@item :allow-nil-initform
|
|
If this option is non-@code{nil}, and the @code{:initform} is @code{nil}, but
|
|
the @code{:type} is specifies something such as @code{string} then allow
|
|
this to pass. The default is to have this option be off. This is
|
|
implemented as an alternative to unbound slots.
|
|
|
|
This option is specific to Emacs, and is not in the CLOS spec.
|
|
|
|
@item :abstract
|
|
A class which is @code{:abstract} cannot be instantiated, and instead
|
|
is used to define an interface which subclasses should implement.
|
|
|
|
This option is specific to Emacs, and is not in the CLOS spec.
|
|
|
|
@item :custom-groups
|
|
This is a list of groups that can be customized within this class. This
|
|
slot is auto-generated when a class is created and need not be
|
|
specified. It can be retrieved with the @code{class-option} command,
|
|
however, to see what groups are available.
|
|
|
|
This option is specific to Emacs, and is not in the CLOS spec.
|
|
|
|
@item :method-invocation-order
|
|
This controls the order in which method resolution occurs for
|
|
methods in cases of multiple inheritance. The order
|
|
affects which method is called first in a tree, and if
|
|
@code{cl-call-next-method} is used, it controls the order in which the
|
|
stack of methods are run.
|
|
|
|
Valid values are:
|
|
|
|
@table @code
|
|
@item :breadth-first
|
|
Search for methods in the class hierarchy in breadth first order.
|
|
This is the default.
|
|
@item :depth-first
|
|
Search for methods in the class hierarchy in a depth first order.
|
|
@item :c3
|
|
Searches for methods in a linearized way that most closely matches
|
|
what CLOS does when a monotonic class structure is defined.
|
|
@end table
|
|
|
|
@xref{Method Invocation}, for more on method invocation order.
|
|
|
|
@item :metaclass
|
|
Unsupported CLOS option. Enables the use of a different base class other
|
|
than @code{standard-class}.
|
|
|
|
@item :default-initargs
|
|
Unsupported CLOS option. Specifies a list of initargs to be used when
|
|
creating new objects. As far as I can tell, this duplicates the
|
|
function of @code{:initform}.
|
|
@end table
|
|
|
|
@xref{CLOS compatibility}, for more details on CLOS tags versus
|
|
@eieio{}-specific tags.
|
|
|
|
@node Making New Objects
|
|
@chapter Making New Objects
|
|
|
|
Suppose we have defined a simple class, such as:
|
|
|
|
@example
|
|
(defclass my-class ()
|
|
( ) "Doc String")
|
|
@end example
|
|
|
|
@noindent
|
|
It is now possible to create objects of that class type.
|
|
|
|
Calling @code{defclass} has defined two new functions. One is the
|
|
constructor @var{my-class}, and the other is the predicate,
|
|
@var{my-class}-p.
|
|
|
|
@defun my-class object-name &rest slots
|
|
|
|
This creates and returns a new object. This object is not assigned to
|
|
anything, and will be garbage collected if not saved. This object
|
|
will be given the string name @var{object-name}. There can be
|
|
multiple objects of the same name, but the name slot provides a handy
|
|
way to keep track of your objects. @var{slots} is just all the slots
|
|
you wish to preset. Any slot set as such @emph{will not} get its
|
|
default value, and any side effects from a slot's @code{:initform}
|
|
that may be a function will not occur.
|
|
|
|
An example pair would appear simply as @code{:value 1}. Of course you
|
|
can do any valid Lispy thing you want with it, such as
|
|
@code{:value (if (boundp 'special-symbol) special-symbol nil)}
|
|
|
|
Example of creating an object from a class:
|
|
|
|
@example
|
|
(my-class :value 3 :reference nil)
|
|
@end example
|
|
|
|
@end defun
|
|
|
|
To create an object from a class symbol, use @code{make-instance}.
|
|
|
|
@defun make-instance class &rest initargs
|
|
@anchor{make-instance}
|
|
Make a new instance of @var{class} based on @var{initargs}.
|
|
@var{class} is a class symbol. For example:
|
|
|
|
@example
|
|
(make-instance 'foo)
|
|
@end example
|
|
|
|
@var{initargs} is a property list with keywords based on the @code{:initarg}
|
|
for each slot. For example:
|
|
|
|
@example
|
|
(make-instance @code{'foo} @code{:slot1} value1 @code{:slotN} valueN)
|
|
@end example
|
|
|
|
@end defun
|
|
|
|
@node Accessing Slots
|
|
@chapter Accessing Slots
|
|
|
|
There are several ways to access slot values in an object.
|
|
The following accessors are defined by CLOS to reference or modify
|
|
slot values, and use the previously mentioned set/ref routines.
|
|
|
|
@defun slot-value object slot
|
|
@anchor{slot-value}
|
|
This function retrieves the value of @var{slot} from @var{object}.
|
|
It can also be used on objects defined by @code{cl-defstruct}.
|
|
|
|
This is a generalized variable that can be used with @code{setf} to
|
|
modify the value stored in @var{slot}.
|
|
@xref{Generalized Variables,,,elisp,GNU Emacs Lisp Reference Manual}.
|
|
@end defun
|
|
|
|
@defun set-slot-value object slot value
|
|
@anchor{set-slot-value}
|
|
This function sets the value of @var{slot} from @var{object}.
|
|
|
|
This is not a CLOS function. It is therefore
|
|
recommended to use @w{@code{(setf (slot-value @var{object} @var{slot})
|
|
@var{value})}} instead.
|
|
@end defun
|
|
|
|
@defun slot-makeunbound object slot
|
|
This function unbinds @var{slot} in @var{object}. Referencing an
|
|
unbound slot can signal an error.
|
|
@end defun
|
|
|
|
The following accessors follow a naming and argument-order conventions
|
|
are similar to those used for referencing vectors
|
|
(@pxref{Vectors,,,elisp,GNU Emacs Lisp Reference Manual}).
|
|
|
|
@defmac oref obj slot
|
|
@anchor{oref}
|
|
This macro retrieves the value stored in @var{obj} in the named
|
|
@var{slot}. Unlike @code{slot-value}, the symbol for @var{slot} must
|
|
not be quoted.
|
|
|
|
This is a generalized variable that can be used with @code{setf} to
|
|
modify the value stored in @var{slot}. @xref{Generalized
|
|
Variables,,,elisp,GNU Emacs Lisp Reference Manual}.
|
|
@end defmac
|
|
|
|
@defmac oref-default class slot
|
|
@anchor{oref-default}
|
|
This macro returns the value of the class-allocated @var{slot} from
|
|
@var{class}.
|
|
|
|
This is a generalized variable that can be used with @code{setf} to
|
|
modify the value stored in @var{slot}. @xref{Generalized
|
|
Variables,,,elisp,GNU Emacs Lisp Reference Manual}.
|
|
@end defmac
|
|
|
|
@defmac oset object slot value
|
|
This macro sets the value behind @var{slot} to @var{value} in
|
|
@var{object}. It returns @var{value}.
|
|
@end defmac
|
|
|
|
@defmac oset-default class slot value
|
|
This macro sets the value for the class-allocated @var{slot} in @var{class} to
|
|
@var{value}.
|
|
|
|
For example, if a user wanted all @code{data-objects} (@pxref{Building
|
|
Classes}) to inform a special object of his own devising when they
|
|
changed, this can be arranged by simply executing this bit of code:
|
|
|
|
@example
|
|
(oset-default data-object reference (list my-special-object))
|
|
@end example
|
|
@end defmac
|
|
|
|
@defun object-add-to-list object slot item &optional append
|
|
@anchor{object-add-to-list}
|
|
In OBJECT's @var{slot}, add @var{item} to the list of elements.
|
|
Optional argument @var{append} indicates we need to append to the list.
|
|
If @var{item} already exists in the list in @var{slot}, then it is not added.
|
|
Comparison is done with @dfn{equal} through the @dfn{member} function call.
|
|
If @var{slot} is unbound, bind it to the list containing @var{item}.
|
|
@end defun
|
|
|
|
@defun object-remove-from-list object slot item
|
|
@anchor{object-remove-from-list}
|
|
In OBJECT's @var{slot}, remove occurrences of @var{item}.
|
|
Deletion is done with @dfn{delete}, which deletes by side effect
|
|
and comparisons are done with @dfn{equal}.
|
|
If @var{slot} is unbound, do nothing.
|
|
@end defun
|
|
|
|
@defun with-slots spec-list object &rest body
|
|
@anchor{with-slots}
|
|
Bind @var{spec-list} lexically to slot values in @var{object}, and execute @var{body}.
|
|
This establishes a lexical environment for referring to the slots in
|
|
the instance named by the given slot-names as though they were
|
|
variables. Within such a context the value of the slot can be
|
|
specified by using its slot name, as if it were a lexically bound
|
|
variable. Both @code{setf} and @code{setq} can be used to set the value of the
|
|
slot.
|
|
|
|
@var{spec-list} is of a form similar to @dfn{let}. For example:
|
|
|
|
@example
|
|
((VAR1 SLOT1)
|
|
SLOT2
|
|
SLOTN
|
|
(VARN+1 SLOTN+1))
|
|
@end example
|
|
|
|
Where each @var{var} is the local variable given to the associated
|
|
@var{slot}. A slot specified without a variable name is given a
|
|
variable name of the same name as the slot.
|
|
|
|
@example
|
|
(defclass myclass () ((x :initform 1)))
|
|
(setq mc (make-instance 'myclass))
|
|
(with-slots (x) mc x) => 1
|
|
(with-slots ((something x)) mc something) => 1
|
|
@end example
|
|
@end defun
|
|
|
|
@node Writing Methods
|
|
@chapter Writing Methods
|
|
|
|
Writing a method in @eieio{} is similar to writing a function. The
|
|
differences are that there are some extra options and there can be
|
|
multiple definitions under the same function symbol.
|
|
|
|
Where a method defines an implementation for a particular data type, a
|
|
@dfn{generic method} accepts any argument, but contains no code. It
|
|
is used to provide the dispatching to the defined methods. A generic
|
|
method has no body, and is merely a symbol upon which methods are
|
|
attached. It also provides the base documentation for what methods
|
|
with that name do.
|
|
|
|
@menu
|
|
* Generics::
|
|
* Methods::
|
|
* Static Methods::
|
|
@end menu
|
|
|
|
@node Generics
|
|
@section Generics
|
|
|
|
Each @eieio{} method has one corresponding generic. This generic
|
|
provides a function binding and the base documentation for the method
|
|
symbol (@pxref{Symbol Components,,,elisp,GNU Emacs Lisp Reference
|
|
Manual}).
|
|
|
|
@defmac cl-defgeneric method arglist [doc-string]
|
|
This macro turns the (unquoted) symbol @var{method} into a function.
|
|
@var{arglist} is the default list of arguments to use (not implemented
|
|
yet). @var{doc-string} is the documentation used for this symbol.
|
|
|
|
A generic function acts as a placeholder for methods. There is no
|
|
need to call @code{cl-defgeneric} yourself, as @code{cl-defmethod} will call
|
|
it if necessary. Currently the argument list is unused.
|
|
|
|
@code{cl-defgeneric} signals an error if you attempt to turn an existing
|
|
Emacs Lisp function into a generic function.
|
|
|
|
You can also create a generic method with @code{cl-defmethod}
|
|
(@pxref{Methods}). When a method is created and there is no generic
|
|
method in place with that name, then a new generic will be created,
|
|
and the new method will use it.
|
|
@end defmac
|
|
|
|
@node Methods
|
|
@section Methods
|
|
|
|
A method is a function that is executed if the arguments passed
|
|
to it matches the method's specializers. Different @eieio{} classes may
|
|
share the same method names.
|
|
|
|
Methods are created with the @code{cl-defmethod} macro, which is similar
|
|
to @code{defun}.
|
|
|
|
@defmac cl-defmethod method [:before | :around | :after ] arglist [doc-string] forms
|
|
|
|
@var{method} is the name of the function to create.
|
|
|
|
@code{:before}, @code{:around}, and @code{:after} specify execution order
|
|
(i.e., when this form is called). If none of these symbols are present, the
|
|
method is said to be a @emph{primary}.
|
|
|
|
@var{arglist} is the list of arguments to this method. The mandatory arguments
|
|
in this list may have a type specializer (see the example below) which means
|
|
that the method will only apply when those arguments match the given type
|
|
specializer. An argument with no type specializer means that the method
|
|
applies regardless of its value.
|
|
|
|
@var{doc-string} is the documentation attached to the implementation.
|
|
All method doc-strings are incorporated into the generic method's
|
|
function documentation.
|
|
|
|
@var{forms} is the body of the function.
|
|
|
|
@end defmac
|
|
|
|
@noindent
|
|
In the following example, we create a method @code{mymethod} for the
|
|
@code{classname} class:
|
|
|
|
@example
|
|
(cl-defmethod mymethod ((obj classname) secondarg)
|
|
"Doc string" )
|
|
@end example
|
|
|
|
@noindent
|
|
This method only executes if the @var{obj} argument passed to it is an
|
|
@eieio{} object of class @code{classname}.
|
|
|
|
A method with no type specializer is a @dfn{default method}. If a given
|
|
class has no implementation, then the default method is called when
|
|
that method is used on a given object of that class.
|
|
|
|
Only one method per combination of specializers and qualifiers (@code{:before},
|
|
@code{:around}, or @code{:after}) is kept. If two @code{cl-defmethod}s appear
|
|
with the same specializers and the same qualifiers, then the second
|
|
implementation replaces the first.
|
|
|
|
When a method is called on an object, but there is no method specified
|
|
for that object, but there is a method specified for object's parent
|
|
class, the parent class's method is called. If there is a method
|
|
defined for both, only the child's method is called. A child method
|
|
may call a parent's method using @code{cl-call-next-method}, described
|
|
below.
|
|
|
|
If multiple methods and default methods are defined for the same
|
|
method and class, they are executed in this order:
|
|
|
|
@enumerate
|
|
@item :around methods
|
|
The most specific @code{:around} method is called first, which may invoke the
|
|
less specific ones via @code{cl-call-next-method}. If it doesn't invoke
|
|
@code{cl-call-next-method}, then no other methods will be executed. When there
|
|
are no more @code{:around} methods to call, falls through to run the other
|
|
(non-@code{:around}) methods.
|
|
@item :before methods
|
|
Called in sequence from most specific to least specific.
|
|
@item primary methods
|
|
The most specific method is called, which may invoke the less specific
|
|
ones via @code{cl-call-next-method}.
|
|
@item :after methods
|
|
Called in sequence from least specific to most specific.
|
|
@end enumerate
|
|
|
|
If no methods exist, Emacs signals a @code{cl-no-applicable-method} error.
|
|
@xref{Signals}. If methods exist but none of them are primary, Emacs
|
|
signals a @code{cl-no-primary-method} error. @xref{Signals}.
|
|
|
|
@defun cl-call-next-method &rest replacement-args
|
|
@anchor{cl-call-next-method}
|
|
|
|
This function calls the superclass method from a subclass method.
|
|
This is the ``next method'' specified in the current method list.
|
|
|
|
If @var{replacement-args} is non-@code{nil}, then use them instead of the
|
|
arguments originally provided to the method.
|
|
|
|
Can only be used from within the lexical body of a primary or around method.
|
|
@end defun
|
|
|
|
@defun cl-next-method-p
|
|
@anchor{cl-next-method-p}
|
|
Non-@code{nil} if there is a next method.
|
|
|
|
Can only be used from within the lexical body of a primary or around method.
|
|
@end defun
|
|
|
|
@node Static Methods
|
|
@section Static Methods
|
|
|
|
Static methods do not depend on an object instance, but instead
|
|
operate on a class. You can create a static method by using
|
|
the @code{subclass} specializer with @code{cl-defmethod}:
|
|
|
|
@example
|
|
(cl-defmethod make-instance ((class (subclass mychild)) &rest args)
|
|
(let ((new (cl-call-next-method)))
|
|
(push new all-my-children)
|
|
new))
|
|
@end example
|
|
|
|
The argument of a static method will be a class rather than an object.
|
|
Use the functions @code{oref-default} or @code{oset-default} which
|
|
will work on a class.
|
|
|
|
A class's @code{make-instance} method is defined as a static
|
|
method.
|
|
|
|
@b{Note:} The @code{subclass} specializer is unique to @eieio{}.
|
|
|
|
@c TODO - Write some more about static methods here
|
|
|
|
@node Method Invocation
|
|
@chapter Method Invocation
|
|
|
|
When classes are defined, you can specify the
|
|
@code{:method-invocation-order}. This is a feature specific to EIEIO.
|
|
|
|
This controls the order in which method resolution occurs for
|
|
methods in cases of multiple inheritance. The order
|
|
affects which method is called first in a tree, and if
|
|
@code{cl-call-next-method} is used, it controls the order in which the
|
|
stack of methods are run.
|
|
|
|
The original EIEIO order turned out to be broken for multiple
|
|
inheritance, but some programs depended on it. As such this option
|
|
was added when the default invocation order was fixed to something
|
|
that made more sense in that case.
|
|
|
|
Valid values are:
|
|
|
|
@table @code
|
|
@item :breadth-first
|
|
Search for methods in the class hierarchy in breadth first order.
|
|
This is the default.
|
|
@item :depth-first
|
|
Search for methods in the class hierarchy in a depth first order.
|
|
@item :c3
|
|
Searches for methods in a linearized way that most closely matches
|
|
what CLOS does when a monotonic class structure is defined.
|
|
|
|
This is derived from the Dylan language documents by
|
|
Kim Barrett et al.: A Monotonic Superclass Linearization for Dylan
|
|
Retrieved from: https://doi.org/10.1145/236338.236343
|
|
@end table
|
|
|
|
@node Predicates
|
|
@chapter Predicates and Utilities
|
|
|
|
Now that we know how to create classes, access slots, and define
|
|
methods, it might be useful to verify that everything is doing ok. To
|
|
help with this a plethora of predicates have been created.
|
|
|
|
@defun find-class symbol &optional errorp
|
|
@anchor{find-class}
|
|
Return the class that @var{symbol} represents.
|
|
If there is no class, @code{nil} is returned if @var{errorp} is @code{nil}.
|
|
If @var{errorp} is non-@code{nil}, @code{wrong-argument-type} is signaled.
|
|
@end defun
|
|
|
|
@defun class-p class
|
|
@anchor{class-p}
|
|
Return @code{t} if @var{class} is a valid class object.
|
|
@var{class} is a symbol.
|
|
@end defun
|
|
|
|
@defun slot-exists-p object-or-class slot
|
|
@anchor{slot-exists-p}
|
|
Non-@code{nil} if @var{object-or-class} has @var{slot}.
|
|
@end defun
|
|
|
|
@defun slot-boundp object slot
|
|
@anchor{slot-boundp}
|
|
Non-@code{nil} if OBJECT's @var{slot} is bound.
|
|
Setting a slot's value makes it bound. Calling @dfn{slot-makeunbound} will
|
|
make a slot unbound.
|
|
@var{object} can be an instance or a class.
|
|
@end defun
|
|
|
|
@defun eieio-class-name class
|
|
Return the class name as a symbol.
|
|
@end defun
|
|
|
|
@defun class-option class option
|
|
Return the value in @var{CLASS} of a given @var{OPTION}.
|
|
For example:
|
|
|
|
@example
|
|
(class-option eieio-default-superclass :documentation)
|
|
@end example
|
|
|
|
Will fetch the documentation string for @code{eieio-default-superclass}.
|
|
@end defun
|
|
|
|
@defun eieio-object-name obj
|
|
Return a string of the form @samp{#<object-class myobjname>} for @var{obj}.
|
|
This should look like Lisp symbols from other parts of Emacs such as
|
|
buffers and processes, and is shorter and cleaner than printing the
|
|
object's record. It is more useful to use @code{object-print} to get
|
|
an object's print form, as this allows the object to add extra display
|
|
information into the symbol.
|
|
@end defun
|
|
|
|
@defun eieio-object-class obj
|
|
Returns the class symbol from @var{obj}.
|
|
@end defun
|
|
|
|
@defun eieio-object-class-name obj
|
|
Returns the symbol of @var{obj}'s class.
|
|
@end defun
|
|
|
|
@defun eieio-class-parents class
|
|
Returns the direct parents class of @var{class}. Returns @code{nil} if
|
|
it is a superclass.
|
|
@end defun
|
|
|
|
@defun eieio-class-parents-fast class
|
|
Just like @code{eieio-class-parents} except it is a macro and no type checking
|
|
is performed.
|
|
@end defun
|
|
|
|
@defun eieio-class-parent class
|
|
Deprecated function which returns the first parent of @var{class}.
|
|
@end defun
|
|
|
|
@defun eieio-class-children class
|
|
Return the list of classes inheriting from @var{class}.
|
|
@end defun
|
|
|
|
@defun eieio-class-children-fast class
|
|
Just like @code{eieio-class-children}, but with no checks.
|
|
@end defun
|
|
|
|
@defun same-class-p obj class
|
|
Returns @code{t} if @var{obj}'s class is the same as @var{class}.
|
|
@end defun
|
|
|
|
@defun object-of-class-p obj class
|
|
Returns @code{t} if @var{obj} inherits anything from @var{class}. This
|
|
is different from @code{same-class-p} because it checks for inheritance.
|
|
@end defun
|
|
|
|
@defun child-of-class-p child class
|
|
Returns @code{t} if @var{child} is a subclass of @var{class}.
|
|
@end defun
|
|
|
|
@defun generic-p method-symbol
|
|
Returns @code{t} if @code{method-symbol} is a generic function, as
|
|
opposed to a regular Emacs Lisp function.
|
|
@end defun
|
|
|
|
@node Association Lists
|
|
@chapter Association Lists
|
|
|
|
Lisp offers the concept of association lists, with primitives such as
|
|
@code{assoc} used to access them. The following functions can be used
|
|
to manage association lists of @eieio{} objects:
|
|
|
|
@defun object-assoc key slot list
|
|
@anchor{object-assoc}
|
|
Return an object if @var{key} is @dfn{equal} to SLOT's value of an object in @var{list}.
|
|
@var{list} is a list of objects whose slots are searched.
|
|
Objects in @var{list} do not need to have a slot named @var{slot}, nor does
|
|
@var{slot} need to be bound. If these errors occur, those objects will
|
|
be ignored.
|
|
@end defun
|
|
|
|
|
|
@defun object-assoc-list slot list
|
|
Return an association list generated by extracting @var{slot} from all
|
|
objects in @var{list}. For each element of @var{list} the @code{car} is
|
|
the value of @var{slot}, and the @code{cdr} is the object it was
|
|
extracted from. This is useful for generating completion tables.
|
|
@end defun
|
|
|
|
@defun eieio-build-class-alist &optional base-class
|
|
Returns an alist of all currently defined classes. This alist is
|
|
suitable for completion lists used by interactive functions to select a
|
|
class. The optional argument @var{base-class} allows the programmer to
|
|
select only a subset of classes which includes @var{base-class} and
|
|
all its subclasses.
|
|
@end defun
|
|
|
|
@node Customizing
|
|
@chapter Customizing Objects
|
|
|
|
@eieio{} supports the Custom facility through two new widget types.
|
|
If a variable is declared as type @code{object}, then full editing of
|
|
slots via the widgets is made possible. This should be used
|
|
carefully, however, because modified objects are cloned, so if there
|
|
are other references to these objects, they will no longer be linked
|
|
together.
|
|
|
|
If you want in place editing of objects, use the following methods:
|
|
|
|
@defun eieio-customize-object object
|
|
Create a custom buffer and insert a widget for editing @var{object}. At
|
|
the end, an @code{Apply} and @code{Reset} button are available. This
|
|
will edit the object "in place" so references to it are also changed.
|
|
There is no effort to prevent multiple edits of a singular object, so
|
|
care must be taken by the user of this function.
|
|
@end defun
|
|
|
|
@defun eieio-custom-widget-insert object flags
|
|
This method inserts an edit object into the current buffer in place.
|
|
It is implemented as @code{(widget-create 'object-edit :value object)}.
|
|
This method is provided as a locale for adding tracking, or
|
|
specializing the widget insert procedure for any object.
|
|
@end defun
|
|
|
|
To define a slot with an object in it, use the @code{object} tag. This
|
|
widget type will be automatically converted to @code{object-edit} if you
|
|
do in place editing of you object.
|
|
|
|
If you want to have additional actions taken when a user clicks on the
|
|
@code{Apply} button, then overload the method @code{eieio-done-customizing}.
|
|
This method does nothing by default, but that may change in the future.
|
|
This would be the best way to make your objects persistent when using
|
|
in-place editing.
|
|
|
|
@section Widget extension
|
|
|
|
When widgets are being created, one new widget extension has been added,
|
|
called the @code{:slotofchoices}. When this occurs in a widget
|
|
definition, all elements after it are removed, and the slot is specifies
|
|
is queried and converted into a series of constants.
|
|
|
|
@example
|
|
(choice (const :tag "None" nil)
|
|
:slotofchoices morestuff)
|
|
@end example
|
|
|
|
and if the slot @code{morestuff} contains @code{(sym1 sym2 sym3)}, the
|
|
above example is converted into:
|
|
|
|
@example
|
|
(choice (const :tag "None" nil)
|
|
(const sym1)
|
|
(const sym2)
|
|
(const sym3))
|
|
@end example
|
|
|
|
This is useful when a given item needs to be selected from a list of
|
|
items defined in this second slot.
|
|
|
|
@node Introspection
|
|
@chapter Introspection
|
|
|
|
Introspection permits a programmer to peek at the contents of a class
|
|
without any previous knowledge of that class. While @eieio{} implements
|
|
objects on top of records, and thus everything is technically visible,
|
|
some functions have been provided. None of these functions are a part
|
|
of CLOS.
|
|
|
|
@defun eieio-class-slots obj
|
|
Return the list of public slots for @var{obj}.
|
|
@end defun
|
|
|
|
@node Base Classes
|
|
@chapter Base Classes
|
|
|
|
All defined classes, if created with no specified parent class,
|
|
inherit from a special class called @code{eieio-default-superclass}.
|
|
@xref{Default Superclass}.
|
|
|
|
Often, it is more convenient to inherit from one of the other base
|
|
classes provided by @eieio{}, which have useful pre-defined
|
|
properties. (Since @eieio{} supports multiple inheritance, you can
|
|
even inherit from more than one of these classes at once.)
|
|
|
|
@menu
|
|
* eieio-instance-inheritor:: Enable value inheritance between instances.
|
|
* eieio-instance-tracker:: Enable self tracking instances.
|
|
* eieio-singleton:: Only one instance of a given class.
|
|
* eieio-persistent:: Enable persistence for a class.
|
|
* eieio-named:: Use the object name as a :name slot.
|
|
* eieio-speedbar:: Enable speedbar support in your objects.
|
|
@end menu
|
|
|
|
@node eieio-instance-inheritor
|
|
@section @code{eieio-instance-inheritor}
|
|
|
|
This class is defined in the package @file{eieio-base}.
|
|
|
|
Instance inheritance is a mechanism whereby the value of a slot in
|
|
object instance can reference the parent instance. If the parent's slot
|
|
value is changed, then the child instance is also changed. If the
|
|
child's slot is set, then the parent's slot is not modified.
|
|
|
|
@deftp {Class} eieio-instance-inheritor parent-instance
|
|
A class whose instances are enabled with instance inheritance.
|
|
The @var{parent-instance} slot indicates the instance which is
|
|
considered the parent of the current instance. Default is @code{nil}.
|
|
@end deftp
|
|
|
|
@cindex @code{clone}
|
|
To use this class, inherit from it with your own class.
|
|
To make a new instance that inherits from and existing instance of your
|
|
class, use the @code{clone} method with additional parameters
|
|
to specify local values.
|
|
|
|
@cindex @code{slot-unbound}
|
|
The @code{eieio-instance-inheritor} class works by causing cloned
|
|
objects to have all slots unbound. This class' @code{slot-unbound}
|
|
method will cause references to unbound slots to be redirected to the
|
|
parent instance. If the parent slot is also unbound, then
|
|
@code{slot-unbound} will signal an error named @code{slot-unbound}.
|
|
|
|
@node eieio-instance-tracker
|
|
@section @code{eieio-instance-tracker}
|
|
|
|
This class is defined in the package @file{eieio-base}.
|
|
|
|
Sometimes it is useful to keep a master list of all instances of a given
|
|
class. The class @code{eieio-instance-tracker} performs this task.
|
|
|
|
@deftp {Class} eieio-instance-tracker tracking-symbol
|
|
Enable instance tracking for this class.
|
|
The slot @var{tracking-symbol} should be initialized in inheritors of
|
|
this class to a symbol created with @code{defvar}. This symbol will
|
|
serve as the variable used as a master list of all objects of the given
|
|
class.
|
|
@end deftp
|
|
|
|
@defmethod eieio-instance-tracker initialize-instance obj slot
|
|
This method is defined as an @code{:after} method.
|
|
It adds new instances to the master list.
|
|
@end defmethod
|
|
|
|
@defmethod eieio-instance-tracker delete-instance obj
|
|
Remove @var{obj} from the master list of instances of this class.
|
|
This may let the garbage collector nab this instance.
|
|
@end defmethod
|
|
|
|
@deffn eieio-instance-tracker-find key slot list-symbol
|
|
This convenience function lets you find instances. @var{key} is the
|
|
value to search for. @var{slot} is the slot to compare @var{KEY}
|
|
against. The function @code{equal} is used for comparison.
|
|
The parameter @var{list-symbol} is the variable symbol which contains the
|
|
list of objects to be searched.
|
|
@end deffn
|
|
|
|
@node eieio-singleton
|
|
@section @code{eieio-singleton}
|
|
|
|
This class is defined in the package @file{eieio-base}.
|
|
|
|
@deftp {Class} eieio-singleton
|
|
Inheriting from the singleton class will guarantee that there will
|
|
only ever be one instance of this class. Multiple calls to
|
|
@code{make-instance} will always return the same object.
|
|
@end deftp
|
|
|
|
@node eieio-persistent
|
|
@section @code{eieio-persistent}
|
|
|
|
This class is defined in the package @file{eieio-base}.
|
|
|
|
If you want an object, or set of objects to be persistent, meaning the
|
|
slot values are important to keep saved between sessions, then you will
|
|
want your top level object to inherit from @code{eieio-persistent}.
|
|
|
|
To make sure your persistent object can be moved, make sure all file
|
|
names stored to disk are made relative with
|
|
@code{eieio-persistent-path-relative}.
|
|
|
|
@deftp {Class} eieio-persistent file file-header-line
|
|
Enables persistence for instances of this class.
|
|
Slot @var{file} with initarg @code{:file} is the file name in which this
|
|
object will be saved.
|
|
Class allocated slot @var{file-header-line} is used with method
|
|
@code{object-write} as a header comment.
|
|
@end deftp
|
|
|
|
All objects can write themselves to a file, but persistent objects have
|
|
several additional methods that aid in maintaining them.
|
|
|
|
@defmethod eieio-persistent eieio-persistent-save obj &optional file
|
|
Write the object @var{obj} to its file.
|
|
If optional argument @var{file} is specified, use that file name
|
|
instead.
|
|
@end defmethod
|
|
|
|
@defmethod eieio-persistent eieio-persistent-path-relative obj file
|
|
Return a file name derived from @var{file} which is relative to the
|
|
stored location of @var{OBJ}. This method should be used to convert
|
|
file names so that they are relative to the save file, making any system
|
|
of files movable from one location to another.
|
|
@end defmethod
|
|
|
|
@defmethod eieio-persistent object-write obj &optional comment
|
|
Like @code{object-write} for @code{standard-object}, but will derive
|
|
a header line comment from the class allocated slot if one is not
|
|
provided.
|
|
@end defmethod
|
|
|
|
@defun eieio-persistent-read filename &optional class allow-subclass
|
|
Read a persistent object from @var{filename}, and return it.
|
|
Signal an error if the object in @var{FILENAME} is not a constructor
|
|
for @var{CLASS}. Optional @var{allow-subclass} says that it is ok for
|
|
@code{eieio-persistent-read} to load in subclasses of class instead of
|
|
being pedantic.
|
|
@end defun
|
|
|
|
@node eieio-named
|
|
@section @code{eieio-named}
|
|
|
|
This class is defined in the package @file{eieio-base}.
|
|
|
|
@deftp {Class} eieio-named
|
|
Object with a name.
|
|
Name storage already occurs in an object. This object provides get/set
|
|
access to it.
|
|
@end deftp
|
|
|
|
@node eieio-speedbar
|
|
@section @code{eieio-speedbar}
|
|
|
|
This class is in package @file{eieio-speedbar}.
|
|
|
|
If a series of class instances map to a tree structure, it is possible
|
|
to cause your classes to be displayable in Speedbar. @xref{Top,,,speedbar}.
|
|
Inheriting from these classes will enable a speedbar major display mode
|
|
with a minimum of effort.
|
|
|
|
@deftp {Class} eieio-speedbar buttontype buttonface
|
|
Enables base speedbar display for a class.
|
|
@cindex @code{speedbar-make-tag-line}
|
|
The slot @var{buttontype} is any of the symbols allowed by the
|
|
function @code{speedbar-make-tag-line} for the @var{exp-button-type}
|
|
argument @xref{Extending,,,speedbar}.
|
|
The slot @var{buttonface} is the face to use for the text of the string
|
|
displayed in speedbar.
|
|
The slots @var{buttontype} and @var{buttonface} are class allocated
|
|
slots, and do not take up space in your instances.
|
|
@end deftp
|
|
|
|
@deftp {Class} eieio-speedbar-directory-button buttontype buttonface
|
|
This class inherits from @code{eieio-speedbar} and initializes
|
|
@var{buttontype} and @var{buttonface} to appear as directory level lines.
|
|
@end deftp
|
|
|
|
@deftp {Class} eieio-speedbar-file-button buttontype buttonface
|
|
This class inherits from @code{eieio-speedbar} and initializes
|
|
@var{buttontype} and @var{buttonface} to appear as file level lines.
|
|
@end deftp
|
|
|
|
To use these classes, inherit from one of them in you class. You can
|
|
use multiple inheritance with them safely. To customize your class for
|
|
speedbar display, override the default values for @var{buttontype} and
|
|
@var{buttonface} to get the desired effects.
|
|
|
|
Useful methods to define for your new class include:
|
|
|
|
@defmethod eieio-speedbar eieio-speedbar-derive-line-path obj depth
|
|
Return a string representing a directory associated with an instance
|
|
of @var{obj}. @var{depth} can be used to index how many levels of
|
|
indentation have been opened by the user where @var{obj} is shown.
|
|
@end defmethod
|
|
|
|
|
|
@defmethod eieio-speedbar eieio-speedbar-description obj
|
|
Return a string description of @var{OBJ}.
|
|
This is shown in the minibuffer or tooltip when the mouse hovers over
|
|
this instance in speedbar.
|
|
@end defmethod
|
|
|
|
@defmethod eieio-speedbar eieio-speedbar-child-description obj
|
|
Return a string representing a description of a child node of @var{obj}
|
|
when that child is not an object. It is often useful to just use
|
|
item info helper functions such as @code{speedbar-item-info-file-helper}.
|
|
@end defmethod
|
|
|
|
@defmethod eieio-speedbar eieio-speedbar-object-buttonname obj
|
|
Return a string which is the text displayed in speedbar for @var{obj}.
|
|
@end defmethod
|
|
|
|
@defmethod eieio-speedbar eieio-speedbar-object-children obj
|
|
Return a list of children of @var{obj}.
|
|
@end defmethod
|
|
|
|
@defmethod eieio-speedbar eieio-speedbar-child-make-tag-lines obj depth
|
|
This method inserts a list of speedbar tag lines for @var{obj} to
|
|
represent its children. Implement this method for your class
|
|
if your children are not objects themselves. You still need to
|
|
implement @code{eieio-speedbar-object-children}.
|
|
|
|
In this method, use techniques specified in the Speedbar manual.
|
|
@xref{Extending,,,speedbar}.
|
|
@end defmethod
|
|
|
|
Some other functions you will need to learn to use are:
|
|
|
|
@deffn eieio-speedbar-create make-map key-map menu name toplevelfn
|
|
Register your object display mode with speedbar.
|
|
@var{make-map} is a function which initialized you keymap.
|
|
@var{key-map} is a symbol you keymap is installed into.
|
|
@var{menu} is an easy menu vector representing menu items specific to your
|
|
object display.
|
|
@var{name} is a short string to use as a name identifying you mode.
|
|
@var{toplevelfn} is a function called which must return a list of
|
|
objects representing those in the instance system you wish to browse in
|
|
speedbar.
|
|
|
|
Read the Extending chapter in the speedbar manual for more information
|
|
on how speedbar modes work
|
|
@xref{Extending,,,speedbar}.
|
|
@end deffn
|
|
|
|
@node Browsing
|
|
@chapter Browsing class trees
|
|
|
|
The command @kbd{M-x eieio-browse} displays a buffer listing all the
|
|
currently loaded classes in Emacs. The classes are listed in an
|
|
indented tree structure, starting from @code{eieio-default-superclass}
|
|
(@pxref{Default Superclass}).
|
|
|
|
With a prefix argument, this command prompts for a class name; it then
|
|
lists only that class and its subclasses.
|
|
|
|
Here is a sample tree from our current example:
|
|
|
|
@example
|
|
eieio-default-superclass
|
|
+--data-object
|
|
+--data-object-symbol
|
|
@end example
|
|
|
|
Note: new classes are consed into the inheritance lists, so the tree
|
|
comes out upside-down.
|
|
|
|
@node Class Values
|
|
@chapter Class Values
|
|
|
|
You can use the normal @code{describe-function} command to retrieve
|
|
information about a class. Running it on constructors will show a
|
|
full description of the generated class. If you call it on a generic
|
|
function, all implementations of that generic function will be listed,
|
|
together with links through which you can directly jump to the source.
|
|
|
|
@node Default Superclass
|
|
@chapter Default Superclass
|
|
|
|
All defined classes, if created with no specified parent class, will
|
|
inherit from a special class stored in
|
|
@code{eieio-default-superclass}. This superclass is quite simple, but
|
|
with it, certain default methods or attributes can be added to all
|
|
objects. In CLOS, this would be named @code{STANDARD-CLASS}, and that
|
|
symbol is an alias to @code{eieio-default-superclass}.
|
|
|
|
Currently, the default superclass is defined as follows:
|
|
|
|
@example
|
|
(defclass eieio-default-superclass nil
|
|
nil
|
|
"Default parent class for classes with no specified parent class.
|
|
Its slots are automatically adopted by classes with no specified
|
|
parents. This class is not stored in the `parent' slot of a class object."
|
|
:abstract t)
|
|
@end example
|
|
|
|
The default superclass implements several methods providing a default
|
|
behavior for all objects created by @eieio{}.
|
|
|
|
@menu
|
|
* Initialization:: How objects are initialized
|
|
* Basic Methods:: Clone, print, and write
|
|
* Signal Handling:: Methods for managing signals.
|
|
@end menu
|
|
|
|
@node Initialization
|
|
@section Initialization
|
|
|
|
When creating an object of any type, you can use its constructor, or
|
|
@code{make-instance}. This, in turns calls the method
|
|
@code{initialize-instance}, which then calls the method
|
|
@code{shared-initialize}.
|
|
|
|
These methods are all implemented on the default superclass so you do
|
|
not need to write them yourself, unless you need to override one of
|
|
their behaviors.
|
|
|
|
Users should not need to call @code{initialize-instance} or
|
|
@code{shared-initialize}, as these are used by @code{make-instance} to
|
|
initialize the object. They are instead provided so that users can
|
|
augment these behaviors.
|
|
|
|
@defun initialize-instance obj &rest slots
|
|
Initialize @var{obj}. Sets slots of @var{obj} with @var{slots} which
|
|
is a list of name/value pairs. These are actually just passed to
|
|
@code{shared-initialize}.
|
|
@end defun
|
|
|
|
@defun shared-initialize obj &rest slots
|
|
Sets slots of @var{obj} with @var{slots} which is a list of name/value
|
|
pairs.
|
|
|
|
This is called from the default constructor.
|
|
@end defun
|
|
|
|
@node Basic Methods
|
|
@section Basic Methods
|
|
|
|
Additional useful methods defined on the base subclass are:
|
|
|
|
@defun clone obj &rest params
|
|
@anchor{clone}
|
|
Make a copy of @var{obj}, and then apply @var{params}.
|
|
@var{params} is a parameter list of the same form as @var{initialize-instance}
|
|
which are applied to change the object. When overloading @dfn{clone}, be
|
|
sure to call @dfn{cl-call-next-method} first and modify the returned object.
|
|
@end defun
|
|
|
|
@defun object-print this &rest strings
|
|
@anchor{object-print}
|
|
Pretty printer for object @var{this}. Call function @dfn{eieio-object-name} with @var{strings}.
|
|
The default method for printing object @var{this} is to use the
|
|
function @dfn{eieio-object-name}.
|
|
|
|
It is sometimes useful to put a summary of the object into the
|
|
default #<notation> string when using eieio browsing tools.
|
|
|
|
Implement this function and specify @var{strings} in a call to
|
|
@dfn{cl-call-next-method} to provide additional summary information.
|
|
When passing in extra strings from child classes, always remember
|
|
to prepend a space.
|
|
|
|
@example
|
|
(defclass data-object ()
|
|
(value)
|
|
"Object containing one data slot.")
|
|
|
|
(cl-defmethod object-print ((this data-object) &optional strings)
|
|
"Return a string with a summary of the data object as part of the name."
|
|
(apply #'cl-call-next-method this
|
|
(format " value: %s" (render this))
|
|
strings))
|
|
@end example
|
|
|
|
Here is what some output could look like:
|
|
@example
|
|
(object-print test-object)
|
|
=> #<data-object test-object value: 3>
|
|
@end example
|
|
@end defun
|
|
|
|
@defun object-write obj &optional comment
|
|
Write @var{obj} onto a stream in a readable fashion. The resulting
|
|
output will be Lisp code which can be used with @code{read} and
|
|
@code{eval} to recover the object. Only slots with @code{:initarg}s
|
|
are written to the stream.
|
|
@end defun
|
|
|
|
@node Signal Handling
|
|
@section Signal Handling
|
|
|
|
The default superclass defines methods for managing error conditions.
|
|
These methods all throw a signal for a particular error condition.
|
|
|
|
By implementing one of these methods for a class, you can change the
|
|
behavior that occurs during one of these error cases, or even ignore
|
|
the error by providing some behavior.
|
|
|
|
@defun slot-missing object slot-name operation &optional new-value
|
|
@anchor{slot-missing}
|
|
Method invoked when an attempt to access a slot in @var{object} fails.
|
|
@var{slot-name} is the name of the failed slot, @var{operation} is the type of access
|
|
that was requested, and optional @var{new-value} is the value that was desired
|
|
to be set.
|
|
|
|
This method is called from @code{slot-value}, @code{set-slot-value},
|
|
and other functions which directly reference slots in EIEIO objects.
|
|
|
|
The default method signals an error of type @code{invalid-slot-name}.
|
|
@xref{Signals}.
|
|
|
|
You may override this behavior, but it is not expected to return in the
|
|
current implementation.
|
|
|
|
This function takes arguments in a different order than in CLOS.
|
|
@end defun
|
|
|
|
@defun slot-unbound object class slot-name fn
|
|
@anchor{slot-unbound}
|
|
Slot unbound is invoked during an attempt to reference an unbound slot.
|
|
@var{object} is the instance of the object being reference. @var{class} is the
|
|
class of @var{object}, and @var{slot-name} is the offending slot. This function
|
|
throws the signal @code{unbound-slot}. You can overload this function and
|
|
return the value to use in place of the unbound value.
|
|
Argument @var{fn} is the function signaling this error.
|
|
Use @dfn{slot-boundp} to determine if a slot is bound or not.
|
|
|
|
In @var{clos}, the argument list is (@var{class} @var{object} @var{slot-name}), but
|
|
@var{eieio} can only dispatch on the first argument, so the first two are swapped.
|
|
@end defun
|
|
|
|
@defun cl-no-applicable-method generic &rest args
|
|
@anchor{cl-no-applicable-method}
|
|
Called if there are no methods applicable for @var{args} in the generic
|
|
function @var{generic}.
|
|
@var{args} are the arguments that were passed to @var{generic}.
|
|
|
|
Implement this for a class to block this signal. The return
|
|
value becomes the return value of the original method call.
|
|
@end defun
|
|
|
|
@defun cl-no-primary-method generic &rest args
|
|
@anchor{cl-no-primary-method}
|
|
Called if there are methods applicable for @var{args} in the generic
|
|
function @var{generic} but they are all qualified.
|
|
@var{args} are the arguments that were passed to @var{generic}.
|
|
|
|
Implement this for a class to block this signal. The return
|
|
value becomes the return value of the original method call.
|
|
@end defun
|
|
|
|
@defun cl-no-next-method generic method &rest args
|
|
@anchor{cl-no-next-method}
|
|
Called from @dfn{cl-call-next-method} when no additional methods are available.
|
|
@var{generic} is the generic function being called on
|
|
@dfn{cl-call-next-method}, @var{method} is the method where
|
|
@dfn{cl-call-next-method} was called, and
|
|
@var{args} are the arguments it is called by.
|
|
This method signals @dfn{cl-no-next-method} by default. Override this
|
|
method to not throw an error, and its return value becomes the
|
|
return value of @dfn{cl-call-next-method}.
|
|
@end defun
|
|
|
|
@node Signals
|
|
@chapter Signals
|
|
|
|
There are new condition names (signals) that can be caught when using
|
|
@eieio{}.
|
|
|
|
@deffn Signal invalid-slot-name obj-or-class slot
|
|
This signal is called when an attempt to reference a slot in an
|
|
@var{obj-or-class} is made, and the @var{slot} is not defined for
|
|
it.
|
|
@end deffn
|
|
|
|
@deffn Signal cl-no-applicable-method generic arguments
|
|
This signal is called when @var{generic} is called, with @var{arguments}
|
|
and nothing is resolved. This occurs when @var{generic} has been
|
|
defined, but the arguments make it impossible for @eieio{} to determine
|
|
which method body to run.
|
|
|
|
To prevent this signal from occurring in your class, implement the
|
|
method @code{cl-no-applicable-method} for your class. This method is
|
|
called when to throw this signal, so implementing this for your class
|
|
allows you block the signal, and perform some work.
|
|
@end deffn
|
|
|
|
@deffn Signal cl-no-primary-method generic arguments
|
|
Like @code{cl-no-applicable-method} but applies when there are some applicable
|
|
methods, but none of them are primary. You can similarly block it by
|
|
implementing a @code{cl-no-primary-method} method.
|
|
@end deffn
|
|
|
|
@deffn Signal cl-no-next-method class arguments
|
|
This signal is called if the function @code{cl-call-next-method} is called
|
|
and there is no next method to be called.
|
|
|
|
Overload the method @code{cl-no-next-method} to protect against this signal.
|
|
@end deffn
|
|
|
|
@deffn Signal invalid-slot-type slot spec value
|
|
This signal is called when an attempt to set @var{slot} is made, and
|
|
@var{value} doesn't match the specified type @var{spec}.
|
|
|
|
In @eieio{}, this is also used if a slot specifier has an invalid value
|
|
during a @code{defclass}.
|
|
@end deffn
|
|
|
|
@deffn Signal unbound-slot object class slot
|
|
This signal is called when an attempt to reference @var{slot} in
|
|
@var{object} is made, and that instance is currently unbound.
|
|
@end deffn
|
|
|
|
@node Naming Conventions
|
|
@chapter Naming Conventions
|
|
|
|
@xref{Tips,,Tips and Conventions,elisp,GNU Emacs Lisp Reference
|
|
Manual}, for a description of Emacs Lisp programming conventions.
|
|
These conventions help ensure that Emacs packages work nicely one
|
|
another, so an @eieio{}-based program should follow them. Here are
|
|
some conventions that apply specifically to @eieio{}-based programs:
|
|
|
|
@itemize
|
|
|
|
@item Come up with a package prefix that is relatively short. Prefix
|
|
all classes, and methods with your prefix. This is a standard
|
|
convention for functions and variables in Emacs.
|
|
|
|
@item Do not prefix method names with the class name. All methods in
|
|
@eieio{} are ``virtual'', and are dynamically dispatched. Anyone can
|
|
override your methods at any time. Your methods should be prefixed
|
|
with your package name.
|
|
|
|
@item Do not prefix slots in your class. The slots are always locally
|
|
scoped to your class, and need no prefixing.
|
|
|
|
@item If your library inherits from other libraries of classes, you
|
|
must ``require'' that library with the @code{require} command.
|
|
|
|
@end itemize
|
|
|
|
@node CLOS compatibility
|
|
@chapter CLOS compatibility
|
|
|
|
Currently, the following functions should behave almost as expected from
|
|
CLOS.
|
|
|
|
@table @code
|
|
|
|
@item defclass
|
|
All slot keywords are available but not all work correctly.
|
|
Slot keyword differences are:
|
|
|
|
@table @asis
|
|
|
|
@item :reader, and :writer tags
|
|
Create methods that signal errors instead of creating an unqualified
|
|
method. You can still create new ones to do its business.
|
|
|
|
@item :accessor
|
|
This should create an unqualified method to access a slot, but
|
|
instead pre-builds a method that gets the slot's value.
|
|
|
|
@item :type
|
|
Specifier uses the @code{typep} function from the @file{cl}
|
|
package. @xref{Type Predicates,,,cl,Common Lisp Extensions}.
|
|
It therefore has the same issues as that package. Extensions include
|
|
the ability to provide object names.
|
|
@end table
|
|
|
|
defclass also supports class options, but does not currently use values
|
|
of @code{:metaclass}, and @code{:default-initargs}.
|
|
|
|
@item make-instance
|
|
Make instance works as expected, however it just uses the @eieio{} instance
|
|
creator automatically generated when a new class is created.
|
|
@xref{Making New Objects}.
|
|
|
|
@item cl-defgeneric
|
|
Creates the desired symbol, and accepts most of the expected arguments of
|
|
CLOS's @code{defgeneric}.
|
|
|
|
@item cl-defmethod
|
|
Accepts most of the expected arguments of CLOS's @code{defmethod}. To type
|
|
cast against a class, the class must exist before @code{cl-defmethod}
|
|
is called.
|
|
|
|
@item cl-call-next-method
|
|
Works just like CLOS's @code{call-next-method}.
|
|
@end table
|
|
|
|
CLOS supports the @code{describe} command, but @eieio{} provides
|
|
support for using the standard @code{describe-function} command on a
|
|
constructor or generic function.
|
|
|
|
When creating a new class (@pxref{Building Classes}) there are several
|
|
new keywords supported by @eieio{}.
|
|
|
|
In @eieio{} tags are in lower case, not mixed case.
|
|
|
|
@node Wish List
|
|
@chapter Wish List
|
|
|
|
@eieio{} is an incomplete implementation of CLOS@. Finding ways to
|
|
improve the compatibility would help make CLOS style programs run
|
|
better in Emacs.
|
|
|
|
Some important compatibility features that would be good to add are:
|
|
|
|
@enumerate
|
|
@item
|
|
Support for metaclasses.
|
|
@item
|
|
Improve integration with the @file{cl} package.
|
|
@end enumerate
|
|
|
|
There are also improvements to be made to allow @eieio{} to operate
|
|
better in the Emacs environment.
|
|
|
|
@enumerate
|
|
@item
|
|
Allow subclassing of Emacs built-in types, such as faces, markers, and
|
|
buffers.
|
|
@item
|
|
Allow method overloading of method-like functions in Emacs.
|
|
@end enumerate
|
|
|
|
@node GNU Free Documentation License
|
|
@appendix GNU Free Documentation License
|
|
@include doclicense.texi
|
|
|
|
@node Function Index
|
|
@unnumbered Function Index
|
|
|
|
@printindex fn
|
|
|
|
@contents
|
|
@bye
|