[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: OO should break when broken

On Monday, September 1, 2003, at 10:38  PM, vkarvone@mappi.helsinki.fi 

> Quoting Colin Putney <cputney@wiresong.ca>:
>> I've snipped large parts of Vesa's post, mostly because he objects to
>> the simplifications I made in order to keep my argument short, but 
>> does
>> not explicitly disagree with my conclusion.
> You have tried to argue that Ellipse should be a subclass of Circle 
> and I
> disagree with that. This should be very clear from my posts, but
> understanding this does require careful thought.

Thanks for clarifying that. Your discursive style seems to leave a lot 
as an exercise for the reader, which I find makes understanding you 
difficult. We apparently don't share many basic assumptions, so what 
appears obvious to you is not at all obvious to me.

>> Again, I think shapes are not a good example to use in discussions of
>> object modeling, because the mathematical classification of shapes 
>> that
>> everyone is familiar with does not map to a class hierarchy that 
>> models
>> those shapes well.
> I basically disagree on this count also, because one learns a great 
> deal
> more on OO by tackling an example that is fairly well defined (a few
> hundred years of exact mathematics) and requires careful thought. At 
> the
> very minimum, the classes in any OO example should have some well 
> defined
> properties that one can use to formally show that subclassing makes 
> sense.
> (Sadly, examples in many low quality introductory OO texts use classes
> whose properties are barely defined if at all.)

Agreed. If I thought Ellipse should be a subclass of Circle, I would 
also think that shapes are a good domain for examining OO modelling.

>>> Stated in another way, the essense of a subclass is to constrain the
>>> set of states of the superclass.
>> Interesting. Would you care to give an example, or explain why you
>> believe this?
> If you reread my previous post, you will find that it talks about the 
> set
> of states that objects of the superclass and the subclass may take 
> (please
> take some time to understand it). The discussion about the states is a 
> big
> part of the reason why I think that the above characterization is
> basically accurate.

Actually I did read your previous post quite carefully. You made a very 
formal assertion. I congratulate you the precision with which you 
described it. What I don't understand us why you believe it to be true.

> It is hard to not come with an example. In fact, I find it more 
> difficult
> to find meaningful subclasses that are not constraining their 
> superclasses
> in any way.
> A simple example would be a LinkedList[WithSlowSize] class that does 
> not
> cache the size (or length or number of nodes in the list) of the list 
> and
> a subclass LinkedListWithFastSize that would cache the size of the 
> list in
> additional state. It is very easy to see that in 
> LinkedListWithFastSize,
> the set of valid states of the superclass portion (the linked list 
> head)
> and the set of valid states of the added state (the size or the number 
> of
> nodes in the linked list) are strongly dependent (specifically, for a
> specific length, only lists that contain exactly that many nodes are 
> valid
> and for a specific list only a single length is valid) and that the 
> set of
> valid states is a small proper subset of the cartesian product of the
> independent parts of the valid state.

Yes, what you say is true. But I don't see how you could characterize 
this as the subclass constraining the superclass. For every valid 
LinkedList, there is a valid LinkedListWithFastSize.

> On the other hand, if the added state in the subclass is independent of
> the superclass portion of the state, then there must be a change in the
> interface specification (an additional constraint) or the subclass 
> would
> simply not generally be useful.

I'm sorry, I don't understand what you mean by this. By "there must be 
a change in the interface specification" do you mean that there must be 
additional methods that use the additional state? If so, why would you 
consider this a constraint?  If there were no additional methods, why 
wouldn't the subclass be useful? Can you give an example?

>> For sake of argument, assume that all the shape classes have to
>> implement a simple interface: #width, #height and #draw.
> Then, for the sake of argument, I'm given the task to implement a 
> function
> that returns the diagonal vector of a tight bounding rectangle for a 
> given
> Circle. A perfectly valid implementation of the function for Circles 
> could
> only call either #width or #height (but not both) and wouldn't work
> correctly when given an Ellipse.

A function? In what context would you want to do that? Up until now, 
the discussion has been about modeling shapes in an object-oriented 
language. We've seen examples in Java and Smalltalk. Are you thinking 
about this in the context of a functional language?

Now if by "function" you mean a method on some other class that has to 
work with circles and ellipses, I'd say that whoever gave you the task 
made a bad design decision. A better way to do it would be to add 
#extent to shape protocol. Circle and Ellipse would have different 
implementations, yes. Polymorphism is what OO is all about.

> In fact, no matter what interface you choose, as long as the interface 
> is
> wide enough to actually make it possible to distinguish between Circles
> and Ellipses, then it is possible to come up with a perfectly valid
> function on Circles that will not work correctly when given an Ellipse.

Any such function is violating the encapsulation of the shape it's 
given. It can be fixed by moving all or part of the function into 
polymophic methods in the shape interface.