[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: OO should break when broken
From: "Guy Steele - Sun Microsystems Labs" <Guy.Steele@sun.com>
To: <cputney@wiresong.ca>; <clements@brinckerhoff.org>
Cc: <ll1-discuss@ai.mit.edu>
Sent: Thursday, September 04, 2003 10:28 PM
Subject: Re: OO should break when broken
...
> Ellipse.java:
> class Ellipse extends Object {
> float long_axis;
> float short_axis;
>
> public Ellipse(float long_axis_init, float short_axis_init)
> {
> long_axis = long_axis_init;
> short_axis = short_axis_init;
> }
> }
>
> Circle.java:
> class Circle extends Ellipse {
>
> public Circle(float radius)
> {
> super(radius, radius);
> }
> }
>
> Very nice, but let
>
> float radius = 3;
> Ellipse e = new Ellipse(radius, radius);
>
> and then, alas,
>
> e instanceof Circle
>
> is false.
This one is somewhat better:
(defclass ellipse ()
((short-radius :accessor short-radius :initform 1.0)
(long-radius :accessor long-radius :initform 2.0)))
(defclass circle (ellipse)
())
(defun circle-p (ellipse)
(= (short-radius ellipse)(long-radius ellipse)))
(defmethod (setf short-radius) :after (value (object ellipse))
(when (circle-p object)
(change-class object 'circle)))
(defmethod (setf long-radius) :after (value (object ellipse))
(when (circle-p object)
(change-class object 'circle)))
(defmethod (setf short-radius) :after (value (object circle))
(unless (circle-p object)
(change-class object 'ellipse)))
(defmethod (setf long-radius) :after (value (object circle))
(unless (circle-p object)
(change-class object 'ellipse)))
It even works:
CL-USER 8 > (setf a (make-instance 'ellipse))
#<ellipse 205EA4A4>
CL-USER 9 > (describe a)
#<ellipse 205EA4A4> is an ellipse
short-radius 1.0
long-radius 2.0
CL-USER 10 > (setf (long-radius a) 1.0)
1.0
CL-USER 11 > (describe a)
#<circle 205EA4A4> is a circle
short-radius 1.0
long-radius 1.0
CL-USER 12 > (setf (short-radius a) 2.0)
2.0
CL-USER 13 > (describe a)
#<ellipse 205EA4A4> is an ellipse
short-radius 2.0
long-radius 1.0
Marc