Re: Clean Object Class Design -- Circle/Ellipse

From: peter_douglass <baisly_at_gis.net>
Date: Thu, 23 Aug 2001 21:33:51 -0400
Message-ID: <3b856b15_at_tobjects.newsource.com>


Marc Gluch wrote in message

>On Sun, 19 Aug 2001 21:19:11 -0400, "peter_douglass" wrote:
 

>>Responding to Marc Gluch:
 ...
>>>I would argue that it's a benefit of being in the subset relationship.
>>>But what exactly is this benefit? The only one that I can see is
>>>the ability to pass integers as arguments to real functions.
>>>You get neither specification nor code reuse (average number of boxes
>>>is code use, to get reuse you need to be able to compose
>>>real functions with integer functions).
 

>>Hmm. Integer and Real are different types, but using the same code for
 both
>>is not code reuse. You apparently have a more restricted view of code
 reuse
>>than I do.

>Not necessarily. As an engineer, I do whatever gets the job done.
>However, in the context of discussing type inheritance (per title of
>Date's article), I am interested in seeing something more than what
>Fortran let me do 30 years ago.

>>Can you give an example of this more restricted sort of code
>>reuse?

>I quoted a few times Smalltalk's Magnitude/Number hierarchy .
>Was that of any help?

I went back and re-read your posts, and I must confess that I am still quite confused. Much of the confusion has nothing to do with how you use the term "code re-use", but since the reference to your posts his here, I will raise my concerns here. In some posts you make a big fuss about the closure of operations and how the multiplicative inverse is not closed over integers. Yet one of the defining operations of Magnitude is "<", which in most languages returns a boolean value, not another magnitude. Thus, the fuss you make regarding the closure of operations over a type seems inconsistant.

  You will need to educate me regarding Smalltalk, as I don't know if there are instances of Magnitude which are not also instances of subclasses, i.e. I don't know if Magnitude is an abstract class. If your point is that subtyping from concrete classes is less useful or elegant than subtyping from abstract classes, then I would probably agree with you. It is perhaps from this perspective that you so vehemently object to the notion of defining circle to be a subtype of ellipse or rational a subtype of real. In my C++ programming I avoid inheritance from concrete classes except when my philosophical position threatens to interfere with my ability to work with my peers. So I will ask you if your point is that subtype inheritance should only be from abstract classes?

>>Let me ask you. Does a subtype, in your opinion, need to be a subclass?

>The over way around. For me, (abstract) types are specifications,
>classes are implementations of these specifications.

>>I ask this because the sense that I'm getting of your objection to
 Date/Badour
>>is that Integer should not be a subtype of Rational because one typically
>>constructs rationals from integers rather than the other way round.
>That's just a tip of the iceberg.

Elaborate all you care to.

>> I would argue that subclassing and subtyping are orthogonal issues, which
>>unfortunately have been merged in most OO languages.

>Do you propose a separate mechamism (unrelated to inheritance)
>for declaring subtype relationship?

Yes.

 >For user-defined types,
>a simple declaration by itself is not enough. You actually have to
>give a prescription for upcasting/conversion.

Yup.

> So you need to introduce
>a formalism for defining similarities between types (and for any two
> sets there is plenty of ways to map elements of one to the other. are
>you going to define them all, or just these that you find useful in
>your app?).

Only those that are useful.

>Is your position that subset should be a formal concept (even though
>any set can be made a sebset of arbitrarily many newly created sets)

yes.

>and inheritance should be a hack for getting work done expediently,
>with no particular relationship to specifications?

Yes, inheritance from a concrete class should not (necessarily) generate a subtype relationship. In this regard, I highly recommend:

Subtyping is not a good ``Match'' for object-oriented languages, by Kim B. Bruce, Adrian Fiech, and Leaf Petersen.

Typing in object-oriented languages: Achieving expressiveness and safety, by Kim B. Bruce.

PolyTOIL: A type-safe polymorphic object-oriented language, by Kim B. Bruce, Adrian Fiech, Angela Schuett, and Robert van Gent.

and as background to the above

On binary methods, by Kim B. Bruce, Luca Cardelli, Giuseppe Castagna, The Hopkins Objects Group, Gary T. Leavens, and Benjamin Pierce.

all of which can theoretically be downloaded from

http://www.cs.williams.edu/~kim/README.html

although downloading does not seem to be working at the moment. The authors argue for separate mechanisms for subtyping and subclassing so that code can be re-used without running into well known problems where a subclass violates LSP.

>(Sorry if I sound extreme, I don't mean to put words in your mouth.
> I appreciate the thoughtfulness that I always find in your posts).
 

>>IMO, there is nothing wrong with using the specification
>> of integers as a basis for the
>>specification of rationals, yet make Integer as subtype of Rational.

>That's where we disagree. IMO, everything is wrong with deriving
>integers from rationals (and, BTW, the other way around).

I don't propose that integers be "derived" from rationals, nor do I think that is Date's proposal. One starts with integers, "derives" rationals, then declares that, by the way, integers are rationals too, so any function that takes rational values as arguments will work if I pass in an integer value.

>>Further, I think one should be able to declare a subtype relationship when
>>there is no code inheritance one way or the other.

>Why?

Because although the definition of rational is likely to use integers, it is likely to not be a subclass. Look again at Magnitude and Boolean. The definition of Magnitude requires the presence of a definition of Boolean. This doesn't mean that Magnitude is a subclass of Boolean. Similarly, Rational would probablynot be a subclass of Integer, although its declaration may have a dependency upon Integer. It would be nice to be able to declare Integer a subtype of Rational.

><snip>
 

>>>>You don't seem to value sub-sets as being sub-types.
>>>>I'm not sure why. For me, a key value
>>>>of types is the ability to include specification information within a
>>>>program, and to have the type-checker reject programs for which the
>>>>included type specifications do not match the program functionality.

>>>But what kind of specification are you talking about?
>>>Signatures, or axiomatizations (invariants)?

>>signatures

>but declaration is not the same as specification.
>Any use of it (by the compiler) is superficial.

Yes, we could take the Smalltalk approach and let any message be sent to any object, with no checking by the compiler. There are many fans of this approach. However, _if_ you value static typing, a superficial declaration that says it's OK to use Integer values where-ever Rational values are expected is a nice convenience.

>>>>Types used in this way are just useful decoration of programs,
>>>> and may be erased without altering the semantics of the program,
>>>>which could otherwise be written in an untyped language.
 

>>Sorry you see little value in the compiler warning you that your
>>declarations and usage don't match.

>This is a different topic - manifest vs latent types.
>I started with Algol and Fortran. Then I spent 15 years writing in
> Lisp, and 10 more writing in Smalltalk. For the last three years
> I've been doing Java. I think I have tried enough of different
>languages to pass a judgement on which feature helps
>and which gets in my way. Obviously, this is just _my_ experience,
>but IMO if you have a design before jumping into coding,
>syntactic (compiler verifiable) type errors will be a rarity.
>Getting a grip on the semantics of the problem domain is a different
>story. You really need to nail down you axioms/invariants.

Perhaps I should keep my fingers away from the keyboard, because we've already had a lengthy static/dynamic manifest/latent typing debate recently, but I'll venture just a little bit. If you have worked out the axioms, (contracts?) how do you ensure that clients of your code (perhaps written by other developers) observe your axioms (contracts)?

>>However, others do, so your claim that
>>declaring subsets as subtypes is useless is debatable.

>My claim is relative to the current state of the
>art/technology/practice. Date's inheritance does not add any value
>to what's already available.
 

> It only confuses people by making
>distinction between values and variables, read and update operations.
>Variables are just names, placeholders for values.
>In pure Lisp (and other functional languages),
> you don't need/use assignment.

Yup. But most OO programmers don't program in functional style, so the distinction between values and variables is important.

>I suspect that it's difficult for Date to come to terms with objects,
>because in the database world all values are immutable
>(don't change state).

The point is that there is division within the database world. On the one hand there are relationists like Date, there are incorrectly implemented "relational" products, and there are non-relational OO products. Date stresses the importance of the value/variable distinction because others neglect that distinction which IMHO leads to confused thinking.

> Neither do functions, until composed into
>recursive feedback loops. Out of a sudden you get values
>that change state -- Kay's "reactive engines".

Functions are still immutable even if they are part of recursive feedback loops.

>Marc Gluch
>Mindtap Inc.
Received on Fri Aug 24 2001 - 03:33:51 CEST

Original text of this message