-
Notifications
You must be signed in to change notification settings - Fork 0
/
chap-4.texi
2920 lines (2160 loc) · 102 KB
/
chap-4.texi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
@node Types and Classes
@chapter Types and Classes
@menu
* Introduction to Types and Classes::
* Types::
* Classes::
* Types and Classes Dictionary::
@end menu
@node Introduction to Types and Classes
@section Introduction to Types and Classes
A @term{type} is a (possibly infinite) set of @term{objects}.
An @term{object} can belong to more than one @term{type}.
@term{Types} are never explicitly represented as @term{objects} by @clisp{}.
Instead, they are referred to indirectly by the use of @term{type specifiers},
which are @term{objects} that denote @term{types}.
New @term{types} can be defined using @symbolref{deftype, SYM}, @symbolref{defstruct, SYM},
@symbolref{defclass, SYM}, and @symbolref{define-condition, SYM}.
@Thefunction{typep}, a set membership test, is used to determine
whether a given @term{object} is of a given @term{type}. The function
@symbolref{subtypep, SYM}, a subset test, is used to determine whether a
given @term{type} is a @term{subtype} of another given @term{type}. The
function @symbolref{type-of, SYM} returns a particular @term{type} to
which a given @term{object} belongs, even though that @term{object}
must belong to one or more other @term{types} as well.
(For example, every @term{object} is @oftype{t},
but @symbolref{type-of, SYM} always returns a @term{type specifier}
for a @term{type} more specific than @symbolref{t, SC}.)
@term{Objects}, not @term{variables}, have @term{types}.
Normally, any @term{variable} can have any @term{object} as its @term{value}.
It is possible to declare that a @term{variable} takes on only
values of a given @term{type} by making an explicit @term{type declaration}.
@term{Types} are arranged in a directed acyclic graph, except
for the presence of equivalences.
@term{Declarations} can be made about @term{types} using @t{declare},
@symbolref{proclaim, SYM}, @symbolref{declaim, SYM}, or @symbolref{the, SYM}.
For more information about @term{declarations},
see @ref{Declarations}.
Among the fundamental @term{objects} of the @CLOS{}@spc{}are @term{classes}.
A @term{class} determines the structure and behavior of a set of
other @term{objects}, which are called its @term{instances}.
Every @term{object} is a @term{direct instance} of a @term{class}.
The @term{class} of an @term{object} determines the set of
operations that can be performed on the @term{object}.
For more information, see @ref{Classes}.
It is possible to write @term{functions} that have behavior @term{specialized}
to the class of the @term{objects} which are their @term{arguments}.
For more information, see @ref{Generic Functions and Methods}.
The @term{class} of the @term{class} of an @term{object}
is called its @newterm{metaclass}.
For more information about @term{metaclasses},
see @ref{Meta-Objects}.
@node Types
@section Types
@menu
* Data Type Definition::
* Type Relationships::
* Type Specifiers::
@end menu
@node Data Type Definition
@subsection Data Type Definition
Information about @term{type} usage is located in
the sections specified in @ref{TypeInfoXrefs, Figure 4.1}.
@ref{ObjectSystemClasses, Figure 4.7}@spc{}lists some @term{classes}
that are particularly relevant to the @CLOS{}.
@ref{StandardizedConditionTypes, Figure 9.1}@spc{}lists the defined @term{condition} @term{types}.
@float Figure,TypeInfoXrefs
@cartouche
@multitable{@ref{Condition System Concepts}}{All types---read and print syntax}
@item @hfil{}@b{Section} @tab Data Type
@item @ref{Classes} @tab Object System types
@item @ref{Slots} @tab Object System types
@item @ref{Objects, Chapter 7 (Objects)} @tab Object System types
@item @ref{Generic Functions and Methods} @tab Object System types
@item @ref{Condition System Concepts} @tab Condition System types
@item @ref{Types and Classes, Chapter 4 (Types and Classes)} @tab Miscellaneous types
@item @ref{Syntax, Chapter 2 (Syntax)} @tab All types---read and print syntax
@item @ref{The Lisp Printer} @tab All types---print syntax
@item @ref{Compilation} @tab All types---compilation issues
@end multitable
@end cartouche
@caption{Cross-References to Data Type Information}
@end float
@node Type Relationships
@subsection Type Relationships
@itemize @bullet{}
@item
@Thetypes{cons}, @symbolref{symbol, SYM}, @symbolref{array, SYM}, @symbolref{number, SYM},
@symbolref{character, SC}, @symbolref{hash-table, SYM},
@symbolref{function, SC},
@symbolref{readtable, SYM}, @symbolref{package, SYM}, @symbolref{pathname, SC}, @symbolref{stream, SYM},
@symbolref{random-state, SYM}, @symbolref{condition, SYM}, @symbolref{restart, SYM},
and any single other @term{type} created by @symbolref{defstruct, SYM},
@symbolref{define-condition, SYM},
or @symbolref{defclass, SYM} are @term{pairwise} @term{disjoint},
except for type relations explicitly established by specifying
@term{superclasses} in @symbolref{defclass, SYM}
or @symbolref{define-condition, SYM}
or the @kwd{include} option of @symbolref{defstruct, SYM}.
@item Any two @term{types} created by @symbolref{defstruct, SYM} are
@term{disjoint} unless
one is a @term{supertype} of the other by virtue of
the @symbolref{defstruct, SYM} @kwd{include} option.
@editornote{KMP: The comments in the source say gray suggested some change
from ``common superclass'' to ``common subclass'' in the following, but the
result looks suspicious to me.}
@item
Any two @term{distinct} @term{classes} created by @symbolref{defclass, SYM}
or @symbolref{define-condition, SYM}
are @term{disjoint} unless they have a common @term{subclass} or
one @term{class} is a @term{subclass} of the other.
@item
An implementation may be extended to add other @term{subtype}
relationships between the specified @term{types}, as long as they do
not violate the type relationships and disjointness requirements
specified here. An implementation may define additional @term{types}
that are @term{subtypes} or @term{supertypes} of any
specified @term{types}, as long as each additional @term{type} is
a @subtypeof{t} and a @supertypeof{nil} and the disjointness requirements
are not violated.
At the discretion of the implementation, either @symbolref{standard-object, SYM}
or @symbolref{structure-object, SYM} might appear in any class precedence list
for a @term{system class} that does not already specify either
@symbolref{standard-object, SYM} or @symbolref{structure-object, SYM}. If it does,
it must precede @theclass{t} and follow all other @term{standardized} @term{classes}.
@end itemize
@node Type Specifiers
@subsection Type Specifiers
@term{Type specifiers} can be @term{symbols}, @term{classes}, or @term{lists}.
@ref{StandardizedAtomicTypeSpecs, Figure 4.2}@spc{}lists @term{symbols} that are
@term{standardized} @term{atomic type specifiers}, and
@ref{StandardizedCompoundTypeSpecNames, Figure 4.3}@spc{}lists
@term{standardized} @term{compound type specifier} @term{names}.
For syntax information, see the dictionary entry for the corresponding @term{type specifier}.
It is possible to define new @term{type specifiers} using
@symbolref{defclass, SYM},
@symbolref{define-condition, SYM},
@symbolref{defstruct, SYM},
or
@symbolref{deftype, SYM}.
@float Figure,StandardizedAtomicTypeSpecs
@cartouche
@multitable{floating-point-invalid-operation}{method-combination}{standard-generic-function}
@item arithmetic-error @tab function @tab simple-condition
@item array @tab generic-function @tab simple-error
@item atom @tab hash-table @tab simple-string
@item base-char @tab integer @tab simple-type-error
@item base-string @tab keyword @tab simple-vector
@item bignum @tab list @tab simple-warning
@item bit @tab logical-pathname @tab single-float
@item bit-vector @tab long-float @tab standard-char
@item broadcast-stream @tab method @tab standard-class
@item built-in-class @tab method-combination @tab standard-generic-function
@item cell-error @tab nil @tab standard-method
@item character @tab null @tab standard-object
@item class @tab number @tab storage-condition
@item compiled-function @tab package @tab stream
@item complex @tab package-error @tab stream-error
@item concatenated-stream @tab parse-error @tab string
@item condition @tab pathname @tab string-stream
@item cons @tab print-not-readable @tab structure-class
@item control-error @tab program-error @tab structure-object
@item division-by-zero @tab random-state @tab style-warning
@item double-float @tab ratio @tab symbol
@item echo-stream @tab rational @tab synonym-stream
@item end-of-file @tab reader-error @tab t
@item error @tab readtable @tab two-way-stream
@item extended-char @tab real @tab type-error
@item file-error @tab restart @tab unbound-slot
@item file-stream @tab sequence @tab unbound-variable
@item fixnum @tab serious-condition @tab undefined-function
@item float @tab short-float @tab unsigned-byte
@item floating-point-inexact @tab signed-byte @tab vector
@item floating-point-invalid-operation @tab simple-array @tab warning
@item floating-point-overflow @tab simple-base-string @tab
@item floating-point-underflow @tab simple-bit-vector @tab
@end multitable
@end cartouche
@caption{Standardized Atomic Type Specifiers}
@end float
If a @term{type specifier} is a @term{list}, the @term{car} of the @term{list}
is a @term{symbol}, and the rest of the @term{list} is subsidiary
@term{type} information. Such a @term{type specifier} is called
a @newterm{compound type specifier}.
Except as explicitly stated otherwise,
the subsidiary items can be unspecified.
The unspecified subsidiary items are indicated
by writing @f{*}. For example, to completely specify
a @term{vector}, the @term{type} of the elements
and the length of the @term{vector} must be present.
@lisp
(vector double-float 100)
@end lisp
The following leaves the length unspecified:
@lisp
(vector double-float *)
@end lisp
The following leaves the element type unspecified:
@lisp
(vector * 100)
@end lisp
Suppose that two @term{type specifiers} are the same except that the first
has a @f{*} where the second has a more explicit specification.
Then the second denotes a @term{subtype}
of the @term{type} denoted by the first.
If a @term{list} has one or more unspecified items at the end,
those items can be dropped.
If dropping all occurrences of @f{*} results in a @term{singleton} @term{list},
then the parentheses can be dropped as well (the list can be replaced
by the @term{symbol} in its @term{car}).
For example,
@tt{(vector double-float *)}
can be abbreviated to @tt{(vector double-float)},
and @tt{(vector * *)} can be abbreviated to @tt{(vector)}
and then to
@tt{vector}.
@float Figure,StandardizedCompoundTypeSpecNames
@cartouche
@multitable{double-float}{simple-array}{simple-base-string}
@item and @tab long-float @tab simple-base-string
@item array @tab member @tab simple-bit-vector
@item base-string @tab mod @tab simple-string
@item bit-vector @tab not @tab simple-vector
@item complex @tab or @tab single-float
@item cons @tab rational @tab string
@item double-float @tab real @tab unsigned-byte
@item eql @tab satisfies @tab values
@item float @tab short-float @tab vector
@item function @tab signed-byte @tab
@item integer @tab simple-array @tab
@end multitable
@end cartouche
@caption{Standardized Compound Type Specifier Names}
@end float
@Thenextfigure{}@spc{}show the @term{defined names} that can be used as
@term{compound type specifier} @term{names}
but that cannot be used as @term{atomic type specifiers}.
@float Figure,fig4.4
@cartouche
@multitable{member}{mod}{satisfies}
@item and @tab mod @tab satisfies
@item eql @tab not @tab values
@item member @tab or @tab
@end multitable
@end cartouche
@caption{Standardized Compound-Only Type Specifier Names}
@end float
New @term{type specifiers} can come into existence in two ways.
@itemize @bullet{}
@item
Defining a structure by using @symbolref{defstruct, SYM} without using
the @kwd{type} specifier or defining a @term{class} by using
@symbolref{defclass, SYM}
or @symbolref{define-condition, SYM}
automatically causes the name of the structure
or class to be a new @term{type specifier} @term{symbol}.
@item
@symbolref{deftype, SYM} can be used to define
@cindex derived type specifier
@dfn{derived type specifiers},
which act as `abbreviations' for other @term{type specifiers}.
@end itemize
A @term{class} @term{object} can be used as a @term{type specifier}.
When used this way, it denotes the set of all members of that @term{class}.
@Thenextfigure{}@spc{}shows some @term{defined names} relating to
@term{types} and @term{declarations}.
@float Figure,TypesAndDeclsNames
@cartouche
@multitable{define-condition}{defstruct}{subtypep}
@item coerce @tab defstruct @tab subtypep
@item declaim @tab deftype @tab the
@item declare @tab ftype @tab type
@item defclass @tab locally @tab type-of
@item define-condition @tab proclaim @tab typep
@end multitable
@end cartouche
@caption{Defined names relating to types and declarations.}
@end float
@Thenextfigure{}@spc{}shows all @term{defined names} that are @term{type specifier} @term{names},
whether for @term{atomic type specifiers} or @term{compound type specifiers};
this list is the union of the lists in @ref{StandardizedAtomicTypeSpecs, Figure 4.2}@spc{}
and @ref{StandardizedCompoundTypeSpecNames, Figure 4.3}.
@float Figure,StandardizedTypeSpecifierNames
@cartouche
@multitable{floating-point-invalid-operation}{method-combination}{standard-generic-function}
@item and @tab function @tab simple-array
@item arithmetic-error @tab generic-function @tab simple-base-string
@item array @tab hash-table @tab simple-bit-vector
@item atom @tab integer @tab simple-condition
@item base-char @tab keyword @tab simple-error
@item base-string @tab list @tab simple-string
@item bignum @tab logical-pathname @tab simple-type-error
@item bit @tab long-float @tab simple-vector
@item bit-vector @tab member @tab simple-warning
@item broadcast-stream @tab method @tab single-float
@item built-in-class @tab method-combination @tab standard-char
@item cell-error @tab mod @tab standard-class
@item character @tab nil @tab standard-generic-function
@item class @tab not @tab standard-method
@item compiled-function @tab null @tab standard-object
@item complex @tab number @tab storage-condition
@item concatenated-stream @tab or @tab stream
@item condition @tab package @tab stream-error
@item cons @tab package-error @tab string
@item control-error @tab parse-error @tab string-stream
@item division-by-zero @tab pathname @tab structure-class
@item double-float @tab print-not-readable @tab structure-object
@item echo-stream @tab program-error @tab style-warning
@item end-of-file @tab random-state @tab symbol
@item eql @tab ratio @tab synonym-stream
@item error @tab rational @tab t
@item extended-char @tab reader-error @tab two-way-stream
@item file-error @tab readtable @tab type-error
@item file-stream @tab real @tab unbound-slot
@item fixnum @tab restart @tab unbound-variable
@item float @tab satisfies @tab undefined-function
@item floating-point-inexact @tab sequence @tab unsigned-byte
@item floating-point-invalid-operation @tab serious-condition @tab values
@item floating-point-overflow @tab short-float @tab vector
@item floating-point-underflow @tab signed-byte @tab warning
@end multitable
@end cartouche
@caption{Standardized Type Specifier Names}
@end float
@node Classes
@section Classes
While the @CLOS{}@spc{}is general enough to describe all @term{standardized} @term{classes}
(including, for example, @symbolref{number, SYM}, @symbolref{hash-table, SYM}, and
@symbolref{symbol, SYM}), @thenextfigure{}@spc{}contains a list of @term{classes} that are
especially relevant to understanding the @CLOS{}.
@float Figure,ObjectSystemClasses
@cartouche
@multitable{generic-function}{standard-generic-function}{structure-object}
@item built-in-class @tab method-combination @tab standard-object
@item class @tab standard-class @tab structure-class
@item generic-function @tab standard-generic-function @tab structure-object
@item method @tab standard-method @tab
@end multitable
@end cartouche
@caption{Object System Classes}
@end float
@menu
* Introduction to Classes::
* Defining Classes::
* Creating Instances of Classes::
* Inheritance::
* Determining the Class Precedence List::
* Redefining Classes::
* Integrating Types and Classes::
@end menu
@node Introduction to Classes
@subsection Introduction to Classes
A @newterm{class} is an @term{object} that determines the structure and behavior
of a set of other @term{objects}, which are called its
@cindex instance
@dfn{instances}.
A @term{class} can inherit structure and behavior from other @term{classes}.
A @term{class} whose definition refers to other @term{classes} for the purpose
of inheriting from them is said to be a @term{subclass} of each of
those @term{classes}. The @term{classes} that are designated for purposes of
inheritance are said to be @term{superclasses} of the inheriting @term{class}.
A @term{class} can have a @term{name}. The @term{function} @symbolref{class-name, SYM}
takes a @term{class} @term{object} and returns its @term{name}.
The @term{name} of an anonymous @term{class} is @nil{}. A @term{symbol}
can @term{name} a @term{class}. The @term{function} @symbolref{find-class, SYM} takes a
@term{symbol} and returns the @term{class} that the @term{symbol} names.
A @term{class} has a @term{proper name} if the @term{name} is a @term{symbol}
and if the @term{name} of the @term{class} names that @term{class}.
That is, a @term{class}@tie{}@mat{C} has the @term{proper name}@tie{}@mat{S} if @mat{S=}
@f{(class-name @mat{C})} and @mat{C=} @f{(find-class @mat{S})}.
Notice that it is possible for
@f{(find-class @mat{S@sub{1}})} @mat{=} @f{(find-class @mat{S@sub{2}})}
and @mat{S@sub{1}@neq{} S@sub{2}}.
If @mat{C=} @f{(find-class @mat{S})}, we say that @mat{C} is the @term{class} @term{named} @mat{S}.
A @term{class} @mat{C@sub{1}} is
a @newterm{direct superclass} of a @term{class} @mat{C@sub{2}}
if @mat{C@sub{2}} explicitly designates @mat{C@sub{1}}
as a @term{superclass} in its definition.
In this case @mat{C@sub{2}} is a @newterm{direct subclass} of @mat{C@sub{1}}.
A @term{class} @mat{C@sub{n}} is a @newterm{superclass} of
a @term{class} @mat{C@sub{1}} if there exists a series of
@term{classes} @mat{C@sub{2},@ldots{},C@sub{n-1}} such that
@mat{C@sub{i+1}} is a @term{direct superclass} of @mat{C@sub{i}} for @mat{1 @leq{} i<n}.
In this case, @mat{C@sub{1}} is a @newterm{subclass} of @mat{C@sub{n}}.
A @term{class} is considered neither a @term{superclass} nor a @term{subclass} of itself.
That is, if @mat{C@sub{1}} is a @term{superclass} of @mat{C@sub{2}},
then @mat{C@sub{1} @neq{} C@sub{2}}.
The set of @term{classes} consisting of some given @term{class} @mat{C}
along with all of its @term{superclasses} is called ``@mat{C} and its superclasses.''
Each @term{class} has a @newterm{class precedence list},
which is a total ordering on the set of the given @term{class} and its @term{superclasses}.
The total ordering is expressed as a list ordered from most specific to least specific.
The @term{class precedence list} is used in several ways. In general, more
specific @term{classes} can @newterm{shadow}@sub{1} features that would
otherwise be inherited from less specific @term{classes}.
The @term{method} selection and combination process uses
the @term{class precedence list} to order @term{methods}
from most specific to least specific.
When a @term{class} is defined, the order in which its direct @term{superclasses}
are mentioned in the defining form is important. Each @term{class} has a
@newterm{local precedence order}, which is a @term{list} consisting of the
@term{class} followed by its @term{direct superclasses} in the order mentioned
in the defining @term{form}.
A @term{class precedence list} is always consistent with the
@term{local precedence order} of each @term{class} in the list.
The @term{classes} in each @term{local precedence order} appear
within the @term{class precedence list} in the same order.
If the @term{local precedence orders} are inconsistent with each other,
no @term{class precedence list} can be constructed, and an error is signaled.
The @term{class precedence list} and its computation is discussed
in @ref{Determining the Class Precedence List}.
@term{classes} are organized into a directed acyclic graph.
There are two distinguished @term{classes}, named @symbolref{t, SC} and @symbolref{standard-object, SYM}.
The @term{class} named @symbolref{t, SC} has no @term{superclasses}.
It is a @term{superclass} of every @term{class} except itself.
The @term{class} named @symbolref{standard-object, SYM} is an @term{instance} of
@theclass{standard-class} and is a @term{superclass} of
every @term{class} that is an @term{instance} of @theclass{standard-class} except itself.
@reviewer{Barmar: This or something like it needs to be said in the introduction.}
There is a mapping from the object system @term{class} space into
the @term{type} space. Many of the standard @term{types} specified
in this document have a corresponding @term{class} that has the same
@term{name} as the @term{type}. Some @term{types} do not have a
corresponding @term{class}. The integration of the @term{type} and @term{class}
systems is discussed in @ref{Integrating Types and Classes}.
@term{Classes} are represented by @term{objects} that are themselves
@term{instances} of @term{classes}.
The @term{class} of the @term{class} of an @term{object} is termed
the @newterm{metaclass} of that @term{object}. When no misinterpretation is
possible, the term @term{metaclass} is used to refer to a @term{class}
that has @term{instances} that are themselves @term{classes}. The @term{metaclass}
determines the form of inheritance used by the @term{classes} that are its
@term{instances} and the representation of the @term{instances} of those @term{classes}.
The @CLOS{}@spc{}provides a default @term{metaclass}, @symbolref{standard-class, SYM}, that is
appropriate for most programs.
Except where otherwise specified, all @term{classes} mentioned in this
standard are @term{instances} of @theclass{standard-class},
all @term{generic functions} are @term{instances}
of @theclass{standard-generic-function},
and all @term{methods} are @term{instances} of @theclass{standard-method}.
@node Standard Metaclasses
@subsubsection Standard Metaclasses
The @CLOS{}@spc{}provides a number of predefined @term{metaclasses}.
These include the @term{classes} @symbolref{standard-class, SYM},
@symbolref{built-in-class, SYM}, and @symbolref{structure-class, SYM}:
@itemize @bullet{}
@item
@Theclass{standard-class} is the default @term{class} of
@term{classes} defined by @symbolref{defclass, SYM}.
@item @Theclass{built-in-class} is the @term{class} whose
@term{instances} are @term{classes} that have special implementations with
restricted capabilities. Any @term{class} that corresponds to a standard
@term{type} might be an @term{instance} of @symbolref{built-in-class, SYM}.
The predefined @term{type} specifiers that are required to have
corresponding @term{classes} are listed in @ref{ClassTypeCorrespondence, Figure 4.8}.
It is @term{implementation-dependent} whether each of these @term{classes}
is implemented as a @term{built-in class}.
@item
All @term{classes} defined by means of @symbolref{defstruct, SYM} are
@term{instances} of @theclass{structure-class}.
@end itemize
@node Defining Classes
@subsection Defining Classes
The macro @symbolref{defclass, SYM} is used to define a new named @term{class}.
The definition of a @term{class} includes:
@itemize @bullet{}
@item The @term{name} of the new @term{class}.
For newly-defined @term{classes} this @term{name} is a @term{proper name}.
@item The list of the direct @term{superclasses} of the new @term{class}.
@item A set of
@cindex slot specifier
@dfn{slot specifiers}.
Each @term{slot specifier} includes the @term{name} of the @term{slot}
and zero or more @term{slot} options. A @term{slot} option pertains
only to a single @term{slot}. If a @term{class} definition contains
two @term{slot specifiers} with the same @term{name}, an error is signaled.
@item A set of @term{class} options.
Each @term{class} option pertains to the @term{class} as a whole.
@end itemize
The @term{slot} options and @term{class} options of
the @symbolref{defclass, SYM} form provide mechanisms for the following:
@itemize @bullet{}
@item Supplying a default initial value @term{form}
for a given @term{slot}.
@item Requesting that @term{methods} for @term{generic functions}
be automatically generated for reading or writing @term{slots}.
@item Controlling whether a given @term{slot} is shared by
all @term{instances}
of the @term{class} or whether each
@term{instance} of the @term{class} has its own @term{slot}.
@item Supplying a set of initialization arguments and initialization
argument defaults to be used in @term{instance} creation.
@item Indicating that the @term{metaclass} is to be other
than the default. The @kwd{metaclass} option is reserved for future use;
an implementation can be extended to make use of the @kwd{metaclass}
option.
@item Indicating the expected @term{type} for the value stored
in the @term{slot}.
@item Indicating the @term{documentation string} for the @term{slot}.
@end itemize
@goodbreak{}
@node Creating Instances of Classes
@subsection Creating Instances of Classes
The generic function @symbolref{make-instance, SYM} creates and returns a new
@term{instance} of a @term{class}.
The @OS{}@spc{}provides several mechanisms for
specifying how a new @term{instance} is to be initialized. For example, it
is possible to specify the initial values for @term{slots} in newly created
@term{instances}
either by giving arguments to @symbolref{make-instance, SYM} or by
providing default initial values. Further initialization activities
can be performed by @term{methods} written for @term{generic functions}
that are
part of the initialization protocol. The complete initialization
protocol is described in @ref{Object Creation and Initialization}.
@node Inheritance
@subsection Inheritance
A @term{class} can inherit @term{methods}, @term{slots},
and some @symbolref{defclass, SYM} options from its @term{superclasses}.
Other sections describe the inheritance of @term{methods},
the inheritance of @term{slots} and @term{slot} options,
and the inheritance of @term{class} options.
@node Examples of Inheritance
@subsubsection Examples of Inheritance
@lisp
(defclass C1 ()
((S1 :initform 5.4 :type number)
(S2 :allocation :class)))
(defclass C2 (C1)
((S1 :initform 5 :type integer)
(S2 :allocation :instance)
(S3 :accessor C2-S3)))
@end lisp
@term{Instances} of the class @f{C1} have a @term{local slot} named @f{S1},
whose default initial value is 5.4 and
whose @term{value} should always be a @term{number}.
The class @f{C1} also has a @term{shared slot} named @f{S2}.
There is a @term{local slot} named @f{S1} in @term{instances} of @f{C2}.
The default initial value of @f{S1} is 5.
The value of @f{S1} should always be of type @f{(and integer number)}.
There are also @term{local slots} named @f{S2} and @f{S3} in @term{instances} of @f{C2}.
The class @f{C2} has a @term{method} for @f{C2-S3} for reading the value of slot @f{S3};
there is also a @term{method} for @f{(setf C2-S3)} that writes the value of @f{S3}.
@node Inheritance of Class Options
@subsubsection Inheritance of Class Options
The @kwd{default-initargs} class option is inherited. The set of
defaulted initialization arguments for a @term{class} is the union of the
sets of initialization arguments supplied in
the @kwd{default-initargs} class options of the @term{class} and its @term{superclasses}.
When more than one default initial value @term{form} is supplied for a given
initialization argument, the default initial value @term{form} that is used
is the one supplied by the @term{class} that is most specific according to
the @term{class precedence list}.
If a given @kwd{default-initargs} class option specifies an
initialization argument of the same @term{name} more than once, an
error @oftype{program-error} is signaled.
@node Determining the Class Precedence List
@subsection Determining the Class Precedence List
The @symbolref{defclass, SYM} form for a @term{class} provides a total ordering
on that @term{class} and its direct @term{superclasses}. This ordering is
called the @newterm{local precedence order}. It is an ordered list of the
@term{class} and its direct @term{superclasses}. The
@newterm{class precedence list} for a class @mat{C} is a total ordering on
@mat{C} and its @term{superclasses} that is consistent with the
@term{local precedence orders} for each of @mat{C} and its @term{superclasses}.
A @term{class} precedes its direct @term{superclasses},
and a direct @term{superclass} precedes all other
direct @term{superclasses} specified to its right
in the @term{superclasses} list of the @symbolref{defclass, SYM} form.
For every class @mat{C}, define
@quotation
@mat{R@sub{C}=@lcurly{}(C,C@sub{1}),(C@sub{1},C@sub{2}),@ldots{},(C@sub{n-1},C@sub{n})@rcurly{}}
@end quotation
where @mat{C@sub{1},@ldots{},C@sub{n}} are
the direct @term{superclasses} of @mat{C} in the order in which
they are mentioned in the @symbolref{defclass, SYM} form. These ordered pairs
generate the total ordering on the class @mat{C} and its direct
@term{superclasses}.
Let @mat{S@sub{C}} be the set of @mat{C} and its @term{superclasses}. Let @mat{R} be
@quotation
@mat{R=@bigcup{}@sub{c@in{} S@sub{C}}R@sub{c}}
@end quotation
.
@reviewer{Barmar: ``Consistent'' needs to be defined, or maybe we should say
``logically consistent''?}
The set @mat{R} might or might not generate a partial ordering, depending on
whether the @mat{R@sub{c}}, @mat{c@in{} S@sub{C}}, are
consistent; it is assumed
that they are consistent and that @mat{R} generates a partial ordering.
When the @mat{R@sub{c}} are not consistent, it is said that @mat{R} is inconsistent.
To compute the @term{class precedence list} for@tie{}@mat{C}@negthinspace{},
topologically sort the elements of @mat{S@sub{C}} with respect to the
partial ordering generated by @mat{R}@negthinspace{}. When the topological
sort must select a @term{class} from a set of two or more
@term{classes}, none of
which are preceded by other @term{classes} with respect to@tie{}@mat{R}@negthinspace{},
the @term{class} selected is chosen deterministically, as described below.
If @mat{R} is inconsistent, an error is signaled.
@goodbreak{}
@node Topological Sorting
@subsubsection Topological Sorting
Topological sorting proceeds by finding a class @mat{C} in@tie{}@mat{S@sub{C}} such
that no other @term{class} precedes that element according to the elements
in@tie{}@mat{R}@negthinspace{}. The class @mat{C} is placed first in the result.
Remove @mat{C} from @mat{S@sub{C}}, and remove all pairs of the form @mat{(C,D)},
@mat{D@in{} S@sub{C}}, from @mat{R}@negthinspace{}. Repeat the process, adding
@term{classes} with no predecessors to the end of the result. Stop when no
element can be found that has no predecessor.
If @mat{S@sub{C}} is not empty and the process has stopped, the set @mat{R} is
inconsistent. If every @term{class} in the finite set of
@term{classes} is preceded
by another, then @mat{R} contains a loop. That is, there is a chain of
classes @mat{C@sub{1},@ldots{},C@sub{n}} such that @mat{C@sub{i}} precedes
@mat{C@sub{i+1}}, @mat{1@leq{} i<n}, and @mat{C@sub{n}} precedes @mat{C@sub{1}}.
Sometimes there are several @term{classes} from @mat{S@sub{C}} with no
predecessors. In this case select the one that has a direct
@term{subclass} rightmost in the @term{class precedence list} computed so far.
(If there is no such candidate @term{class}, @mat{R} does not generate
a partial ordering---the @mat{R@sub{c}}, @mat{c@in{} S@sub{C}}, are inconsistent.)
In more precise terms, let @mat{@lcurly{}N@sub{1},@ldots{},N@sub{m}@rcurly{}}, @mat{m@geq{} 2}, be
the @term{classes} from @mat{S@sub{C}} with no predecessors. Let @mat{(C@sub{1}@ldots{} C@sub{n})}, @mat{n@geq{} 1}, be the @term{class precedence list}
constructed so far. @mat{C@sub{1}} is the most specific @term{class}, and @mat{C@sub{n}} is the least specific. Let @mat{1@leq{} j@leq{} n} be the largest number
such that there exists an @mat{i} where @mat{1@leq{} i@leq{} m} and @mat{N@sub{i}}
is a direct @term{superclass} of @mat{C@sub{j}}; @mat{N@sub{i}} is placed next.
The effect of this rule for selecting from a set of @term{classes} with no
predecessors is that the @term{classes} in a simple @term{superclass} chain are
adjacent in the @term{class precedence list} and that @term{classes} in each
relatively separated subgraph are adjacent in the @term{class precedence list}.
For example, let @mat{T@sub{1}} and @mat{T@sub{2}} be subgraphs whose only
element in common is the class @mat{J}@negthinspace{}.
Suppose that no superclass of @mat{J} appears in either @mat{T@sub{1}} or @mat{T@sub{2}},
and that @mat{J} is in the superclass chain of every class in both @mat{T@sub{1}} and @mat{T@sub{2}}.
Let @mat{C@sub{1}} be the bottom of @mat{T@sub{1}};
and let @mat{C@sub{2}} be the bottom of @mat{T@sub{2}}.
Suppose @mat{C} is a @term{class} whose direct @term{superclasses}
are @mat{C@sub{1}} and @mat{C@sub{2}} in that order, then the @term{class precedence list}
for @mat{C} starts with @mat{C} and is followed by
all @term{classes} in @mat{T@sub{1}} except @mat{J}.
All the @term{classes} of @mat{T@sub{2}} are next.
The @term{class} @mat{J} and its @term{superclasses} appear last.
@node Examples of Class Precedence List Determination
@subsubsection Examples of Class Precedence List Determination
This example determines a @term{class precedence list} for the
class @f{pie}. The following @term{classes} are defined:
@lisp
(defclass pie (apple cinnamon) ())
(defclass apple (fruit) ())
(defclass cinnamon (spice) ())
(defclass fruit (food) ())
(defclass spice (food) ())
(defclass food () ())
@end lisp
The set @mat{S@sub{pie}}@tie{}@mat{=} @mat{@lcurly{}}@tt{pie, apple, cinnamon, fruit, spice, food,
standard-object, t}@mat{@rcurly{}}. The set @mat{R}@tie{}@mat{=} @mat{@lcurly{}}@tt{(pie, apple),
(apple, cinnamon), (apple, fruit), (cinnamon, spice), @hfil{}@break{}
(fruit, food), (spice, food), (food, standard-object), (standard-object,
t)}@mat{@rcurly{}}.
The class @f{pie} is not preceded by anything, so it comes first;
the result so far is @tt{(pie)}. Remove @f{pie} from @mat{S} and pairs
mentioning @f{pie} from @mat{R} to get @mat{S}@tie{}@mat{=} @mat{@lcurly{}}@tt{apple, cinnamon,
fruit, spice, food, standard-object, t}@mat{@rcurly{}} and @mat{R}@tie{}@mat{=}@tie{}@mat{@lcurly{}}@tt{
(apple, cinnamon), (apple, fruit), (cinnamon, spice),@hfil{}@break{} (fruit,
food), (spice, food), (food, standard-object),
(standard-object, t)}@mat{@rcurly{}}.
The class @f{apple} is not preceded by anything, so it is next; the
result is @tt{(pie apple)}. Removing @f{apple} and the relevant
pairs results in @mat{S}@tie{}@mat{=} @mat{@lcurly{}}@tt{cinnamon, fruit, spice, food,
standard-object, t}@mat{@rcurly{}} and @mat{R}@tie{}@mat{=} @mat{@lcurly{}}@tt{(cinnamon, spice),
(fruit, food), (spice, food), (food, standard-object),@hfil{}@break{}
(standard-object, t)}@mat{@rcurly{}}.
The classes @f{cinnamon} and @tt{fruit} are not preceded by
anything, so the one with a direct @term{subclass} rightmost in the
@term{class precedence list} computed so far goes next. The class @f{apple} is a
direct @term{subclass} of @tt{fruit}, and the class @f{pie} is a direct
@term{subclass} of @f{cinnamon}. Because @f{apple} appears to the right
of @f{pie} in the @term{class precedence list},
@tt{fruit} goes next, and the
result so far is @tt{(pie apple fruit)}. @mat{S}@tie{}@mat{=} @mat{@lcurly{}}@tt{cinnamon,
spice, food, standard-object, t}@mat{@rcurly{}}; @mat{R}@tie{}@mat{=} @mat{@lcurly{}}@tt{(cinnamon,
spice), (spice, food),@hfil{}@break{} (food, standard-object),
(standard-object, t)}@mat{@rcurly{}}.
The class @f{cinnamon} is next, giving the result so far as @tt{
(pie apple fruit cinnamon)}. At this point @mat{S}@tie{}@mat{=} @mat{@lcurly{}}@tt{spice,
food, standard-object, t}@mat{@rcurly{}}; @mat{R}@tie{}@mat{=} @mat{@lcurly{}}@tt{(spice, food), (food,
standard-object), (standard-object, t)}@mat{@rcurly{}}.
The classes @f{spice}, @f{food}, @symbolref{standard-object, SYM}, and
@symbolref{t, SC} are added in that order, and the @term{class precedence list}
is @f{(pie apple fruit cinnamon spice food standard-object t)}.
It is possible to write a set of @term{class} definitions that cannot be
ordered. For example:
@lisp
(defclass new-class (fruit apple) ())
(defclass apple (fruit) ())
@end lisp
The class @f{fruit} must precede @f{apple}
because the local ordering of @term{superclasses} must be preserved.
The class @f{apple} must precede @f{fruit}
because a @term{class} always precedes its own @term{superclasses}.
When this situation occurs, an error is signaled, as happens here
when the system tries to compute the @term{class precedence list}
of @f{new-class}.
The following might appear to be a conflicting set of definitions:
@lisp
(defclass pie (apple cinnamon) ())
(defclass pastry (cinnamon apple) ())
(defclass apple () ())
(defclass cinnamon () ())
@end lisp
The @term{class precedence list} for @f{pie} is
@f{(pie apple cinnamon standard-object t)}.
The @term{class precedence list} for @f{pastry} is
@f{(pastry cinnamon apple standard-object t)}.
It is not a problem for @f{apple} to precede @f{cinnamon} in the
ordering of the @term{superclasses} of @f{pie} but not in the ordering for
@f{pastry}. However, it is not possible to build a new @term{class} that
has both @f{pie} and @f{pastry} as @term{superclasses}.
@node Redefining Classes
@subsection Redefining Classes
A @term{class} that is a @term{direct instance} of @symbolref{standard-class, SYM} can
be redefined if the new @term{class} is also
a @term{direct instance} of @symbolref{standard-class, SYM}.
Redefining a @term{class} modifies the existing
@term{class} @term{object} to reflect the new @term{class} definition; it does not
create a new @term{class} @term{object} for the @term{class}.
Any @term{method} @term{object} created by a @kwd{reader}, @kwd{writer},
or @kwd{accessor} option specified by the old @symbolref{defclass, SYM} form is
removed from the corresponding @term{generic function}.
@term{Methods} specified by the new @symbolref{defclass, SYM} form are added.
When the class @mat{C} is redefined, changes are propagated to its @term{instances}
and to @term{instances} of any of its @term{subclasses}. Updating such an
@term{instance} occurs at an @term{implementation-dependent} time, but no later than
the next time a @term{slot}
of that @term{instance} is read or written. Updating an
@term{instance}
does not change its identity as defined by @thefunction{eq}.
The updating process may change the @term{slots} of that
particular @term{instance},
but it does not create a new @term{instance}. Whether
updating an @term{instance} consumes storage is @term{implementation-dependent}.
Note that redefining a @term{class} may cause @term{slots} to be added or
deleted. If a @term{class} is redefined in a way that changes the set of
@term{local slots} @term{accessible} in @term{instances}, the @term{instances}
are updated. It is @term{implementation-dependent} whether @term{instances}
are updated if a @term{class} is redefined in a way that does not change
the set of @term{local slots} @term{accessible} in @term{instances}.
The value of a @term{slot}
that is specified as shared both in the old @term{class}
and in the new @term{class} is retained.
If such a @term{shared slot} was unbound
in the old @term{class}, it is unbound in the new @term{class}.
@term{Slots} that
were local in the old @term{class} and that are shared in the new
@term{class} are
initialized. Newly added @term{shared slots} are initialized.
Each newly added @term{shared slot} is set to the result of evaluating the
@term{captured initialization form} for the @term{slot} that was specified
in the @symbolref{defclass, SYM} @term{form} for the new @term{class}.
If there was no @term{initialization form}, the @term{slot} is unbound.
If a @term{class} is redefined in such a way that the set of
@term{local slots} @term{accessible} in an @term{instance} of the @term{class}
is changed, a two-step process of updating the @term{instances} of the
@term{class} takes place. The process may be explicitly started by
invoking the generic function @symbolref{make-instances-obsolete, SYM}. This
two-step process can happen in other circumstances in some implementations.
For example, in some implementations this two-step process is
triggered if the order of @term{slots} in storage is changed.
The first step modifies the structure of the @term{instance} by adding new
@term{local slots} and discarding @term{local slots} that are not
defined in the new version of the @term{class}. The second step
initializes the newly-added @term{local slots} and performs any other
user-defined actions. These two steps are further specified
in the next two sections.
@node Modifying the Structure of Instances
@subsubsection Modifying the Structure of Instances
@reviewer{Barmar: What about shared slots that are deleted?}
The first step modifies the structure of @term{instances} of the redefined
@term{class} to conform to its new @term{class} definition.
@term{Local slots} specified
by the new @term{class} definition that are not specified as either local or
shared by the old @term{class} are added, and @term{slots}
not specified as either
local or shared by the new @term{class} definition that are specified as
local by the old @term{class} are discarded.
The @term{names} of these added and discarded
@term{slots} are passed as arguments
to @symbolref{update-instance-for-redefined-class, SYM}
as described in the next section.
The values of @term{local slots} specified by both the new and old
@term{classes} are retained. If such a @term{local slot} was unbound,
it remains unbound.