Re: colored point redux

Pascal Costanza <[email protected]> Sun, 25 Feb 2007 12:45:19 +0100
Newsgroups gmane.comp.lang.lightweight
Message-ID <[email protected]>
On 25 Feb 2007, at 04:23, Vadim Nasardinov wrote:

> On Saturday 24 February 2007 16:16, Pascal Costanza wrote:
>> (defgeneric eqv (obj1 obj2)
>>    (:method-combination and)
>>    (:method and (obj1 obj2)
>>     (eql (class-of obj1) (class-of obj2))))
> [...]
>> Better?
>
> Much better because it's more honest.  We have now completely
> abandoned any pretense of Liskov substitutability: 'COLOR-POINT is no
> longer a subtype of 'COLOR.  Which is as it should be.  If we are
> completely honest, however, we should take this a step further and
> change the IS-A relationship to HAS-A.

...and this relates to generic functions how?

[If you want to break the inheritance chain, that's trivial to do:

(defclass point ()
   ((x :initarg :x reader x)
    (y :initarg :y reader y)))

(defclass color-point ()
   ((x :initarg :x reader x)
    (y :initarg :y reader y)
    (c :initarg :color reader color)))

Adapting the eqv methods is left as an exercise to the reader.]

> As Eric Gamma says, "Favor composition over inheritance":

Yes, just another opinion.

> Which brings us to:
>
>  | public final class Point {
>  |     private final int x;
>  |     private final int y;
>  |
>  |     public Point(int x, int y) {
>  |         this.x = x;
>  |         this.y = y;
>  |     }
>  |
>  |     public int getX() { return x; }
>  |     public int getY() { return y; }
>  |
>  |     public boolean equals(Object obj) {
>  |         if (!(obj instanceof Point)) { return false; }
>  |         Point that = (Point) obj;
>  |         return this.x == that.x && this.y == that.y;
>  |     }
>  | }
>  |
>  | public final class ColorPoint {
>  |     public enum Color {
>  |         COLORLESS, GRUE;
>  |     }
>  |
>  |     private final Color color;
>  |     private final Point point;
>  |
>  |     public ColorPoint(Color color, int x, int y) {
>  |         if (color == null) { throw new NullPointerException 
> ("color"); }
>  |         this.color = color;
>  |         this.point = new Point(x, y);
>  |     }
>  |
>  |     public Color getColor() { return color; }
>  |     public Point getPoint() { return point; }
>  |
>  |     public boolean equals(Object obj) {
>  |         if (!(obj instanceof ColorPoint)) { return false; }
>  |
>  |         ColorPoint that = (ColorPoint) obj;
>  |         return this.color.equals(that.color) && this.point.equals 
> (that.point);
>  |     }
>  | }
>
> No schmultiple dispatch needed.

This isn't about necessity. We can easily provide implementations of  
this in Pascal, C, assembly language, Turing machines, what have you.

But what do you think the following lines simulate?

[...]
>  |         if (!(obj instanceof Point)) { return false; }
>  |         Point that = (Point) obj;
[...]

and

[...]
>  |         if (!(obj instanceof ColorPoint)) { return false; }
>  |
>  |         ColorPoint that = (ColorPoint) obj;
[...]


> Why don't we talk about something really important and interesting
> instead?  Say, loops vs. tail-recursive iteration.

...because this discussion is not about properties of equivalence  
predicates, not about substitutability, and not about iteration  
constructs either.



Pascal

-- 
Pascal Costanza, mailto:[email protected], http://p-cos.net
Vrije Universiteit Brussel, Programming Technology Lab
Pleinlaan 2, B-1050 Brussel, Belgium