This repository was archived by the owner on Nov 8, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathabstract-classes.lisp
More file actions
169 lines (141 loc) · 5.44 KB
/
abstract-classes.lisp
File metadata and controls
169 lines (141 loc) · 5.44 KB
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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -*- Mode: Lisp -*- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; File - abstract-classes.lisp
;; Description - Abstract classes in CL
;; Author - Tim Bradshaw (tfb at lostwithiel)
;; Created On - Sun Dec 10 18:21:40 2000
;; Last Modified On - Tue Apr 30 14:23:27 2002
;; Last Modified By - Tim Bradshaw (tfb at lostwithiel)
;; Update Count - 14
;; Status - Unknown
;;
;; $Id: //depot/www-tfeb-org/before-2013-prune/www-tfeb-org/html/programs/lisp/abstract-classes.lisp#1 $
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Abstract classes
;;;
;;; abstract-classes.lisp is copyright 2000-2001 by me, Tim Bradshaw,
;;; and may be used for any purpose whatsoever by anyone. It has no
;;; warranty whatsoever. I would appreciate acknowledgement if you use
;;; it in anger, and I would also very much appreciate any feedback or
;;; bug fixes.
;;;
(defpackage :org.tfeb.hax.abstract-classes
(:nicknames :org.tfeb.hax.final-classes)
;; use whatever you need to get the MOP
(:use :cl
#+allegro :clos
#+cmu :pcl
#+lispworks :hcl)
;; CMU needs to get these things from PCL, not CL, as they are
;; different because it has this weirdo wrapper stuff such that
;; cl:standard-class is not pcl::standard-class & so on. This will,
;; I hope, go away at some point, but it's true for cmucl 18c
;; 2000-09-07.
#+cmu
(:shadowing-import-from :pcl #:standard-class #:built-in-class
#:find-class #:class-name #:class-of)
#+genera
(:import-from :clos-internals #:validate-superclass)
(:export #:abstract-class
#:define-abstract-class
#:final-class
#:define-final-class))
(in-package :org.tfeb.hax.abstract-classes)
(provide :org.tfeb.hax.abstract-classes)
(provide :org.tfeb.hax.final-classes)
(defclass abstract-class (standard-class)
()
(:documentation "The class of abstract classes"))
(defmethod make-instance ((c abstract-class) &rest junk)
(declare (ignore junk))
(error "Trying to make an instance of ~A which is an abstract class"
(class-name c)))
;;; The MOP requires this, but it's not clear that implementations do.
;;; VALIDATE-SUPERCLASS specifies when a superclass is suitable for a
;;; subclass. You have to be pretty specific, It's probably not in
;;; general safe to do what we do here.
;;;
(defmethod validate-superclass ((class abstract-class)
(superclass standard-class))
;; This is, in general, somewhat too permissive, but we are going to
;; allow any instance of (a subclass of) STANDARD-CLASS to act as a
;; superclass of any instance of ABSTRACT-CLASS...
t)
(defmethod validate-superclass ((class standard-class)
(superclass abstract-class))
;; ... and the other way around.
t)
;;; I don't want to have to say ... (:metaclass abstract-class), but
;;; there is no easy hook into processing the options to DEFCLASS:
;;; ENSURE-CLASS-USING-CLASS, which would be the logical place to do
;;; this, is called with a class of NIL if there is no existing class,
;;; and so can't usefully be specialized.
;;;
(defmacro define-abstract-class (class supers slots &rest options)
(when (assoc ':metaclass options)
(error "Defining an abstract class with a metaclass?"))
`(defclass ,class ,supers ,slots
,@options
(:metaclass abstract-class)))
;;; Samples of abstract classes
#||
(define-abstract-class abstract-thing ()
((s :accessor thing-s)))
(defclass thing (abstract-thing)
((s :initform 1)))
||#
;;; Benchmarks: for ACL 6.0 there is no performance hit.
#||
(define-abstract-class ac () ())
(defclass ac-instantiable (ac) ())
(defclass nac () ())
(defclass nac-instantiable (nac) ())
(defun make-n-aci (n)
(declare (type fixnum n)
(optimize speed))
(loop repeat n
do (make-instance 'ac-instantiable)))
(defun make-n-naci (n)
(declare (type fixnum n)
(optimize speed))
(loop repeat n
do (make-instance 'nac-instantiable)))
(defun make-n-general (n cn)
(declare (type fixnum n)
(optimize speed))
(loop repeat n
do (make-instance cn)))
||#
;;;; Final classes
;;;
;;; Classes which may not be subclassed.
;;;
;;; I just know someone is going to ask for an abstract final class.
(defclass final-class (standard-class)
()
(:documentation "The class of classes which may not be subclassed"))
;;; The MOP requires this, but it's not clear that implementations do.
;;; VALIDATE-SUPERCLASS specifies when a superclass is suitable for a
;;; subclass. You have to be pretty specific, It's probably not in
;;; general safe to do what we do here.
;;;
(defmethod validate-superclass ((class final-class)
(superclass standard-class))
;; This is, in general, somewhat too permissive, but we are going to
;; allow any instance of (a subclass of) STANDARD-CLASS to act as a
;; superclass of any instance of ABSTRACT-CLASS...
t)
(defmethod validate-superclass ((class standard-class)
(superclass final-class))
(error "Attempting to subclass a final class"))
;;; I don't want to have to say ... (:metaclass final-class), but
;;; there is no easy hook into processing the options to DEFCLASS:
;;; ENSURE-CLASS-USING-CLASS, which would be the logical place to do
;;; this, is called with a class of NIL if there is no existing class,
;;; and so can't usefully be specialized.
;;;
(defmacro define-final-class (class supers slots &rest options)
(when (assoc ':metaclass options)
(error "Defining a final class with a metaclass?"))
`(defclass ,class ,supers ,slots
,@options
(:metaclass final-class)))