I have an abstract class with one defined read-only slot named storage-size
:
(defclass digital-media (is-a USER)
(role abstract)
(slot storage-size
(type INTEGER)
(default -1)
(access read-only)
(visibility public)))
I've attached a primary message handler to my abstract class which references the same storage-size
slot.
(defmessage-handler digital-media read-storage primary (?offset ?size)
(if (or (< ?offset 0) (>= ?offset ?self:storage-size))
then
(printout t "Read offset " ?offset " is out of bounds, max storage size is " ?self:storage-size crlf)
(halt))
(printout t "Still running for some reason..." crlf))
When making a concrete class, the inherited field works as expected only if it's implicitly declared:
(defclass compact-disk (is-a digital-media)
(role concrete))
(make-instance my-disk of compact-disk)
(send [my-disk] print)
; [my-disk] of compact-disk
; (storage-size -1)
(send [my-disk] read-storage 128 1024)
; Read offset 128 is out of bounds, max storage size is -1
However, when I provide a default value for it the message handler doesn't work:
(defclass compact-disk (is-a digital-media)
(role concrete)
(slot storage-size
(source composite)
(default 650)))
(make-instance my-disk of compact-disk)
(send [my-disk] print)
; [my-disk] of compact-disk
; (storage-size 650)
(send [my-disk] read-storage 128 1024)
; [MSGPASS3] Static reference to slot storage-size of class digital-media does not apply to [my-disk] of compact-disk
; [ARGACCES5] Function >= expected argument #2 to be of type integer or float
; [PRCCODE4] Execution halted during the actions of message-handler read-storage primary in class digital-media
; FALSE
I don't fully understand the rationale, but when you change the slot facets for a subclass, the superclass message-handlers can't use slot shorthand references for that slot when called by an instance of the subclass. So in the read-storage handler you'll need to change ?self:storage-size to (send ?self get-storage-size).
I suppose this enforces encapsulation of the superclass. For example, the read-storage message-handler knows the ?self:storage-size reference must be an integer and that it's not possible for a subclass to redefine the type of this slot to a string and then invoke this message-handler with a subclass instance containing a string rather than an integer value for the slot.