Re: Clean Object Class Design -- Circle/Ellipse

From: Dmitry A. Kazakov <dmitry_at_elros.cbb-automation.de>
Date: Sun, 02 Sep 2001 14:30:29 GMT
Message-ID: <3b92124a.2165876_at_news.cis.dfn.de>


On Sun, 2 Sep 2001 00:37:24 -0400, "Bob Badour" <bbadour_at_golden.net> wrote:

>>>Any value has multiple types: its most-specific type and all of its
>>>inherited types.
>>
>>We disagree here. Any value has exactly one type.
>
>If we accept your assumption that no such thing as subtype exists, we can
>end this conversation now. The conversation is, after all, a discussion of
>subtype.

How the view that any value has a type disallows subtypes?

If you define subtype as a subset then all other follows. Other people are saying that subtype is a LSP subtype with all the consequences. My point is that both deinitions are unsatisfactory.

>>>>>>Unfortunately most of OO languages do not differentiate them.
>>>>>
>>>>>Most OO languages do have the notion of a most-specific type, a declared
>>>>>type and a general (polymorphic) type.
>>>>
>>>>Yes, but they do not differentiate specific and class-wide types.
>>>
>>>You are again confusing things by introducing undefined, unecessary new
>>>terminology. "class-wide type" is meaningless.
>>
>>It is by no means meaningless nor new. For a definition see Ada
>>Reference Manual.
>
>I have no interest in reading the ADA reference manual. This thread is in
>comp.object not in comp.lang.ada -- it's not even cross-posted there.
>
>>The term "class" is used for a set of types derived
>>from a given one.
>
>This is not the accepted use of the term "class" in OO. The ISO standard
>vocabulary for programming languages equates "class" with data type.

Nice to have several words for same thing ...

>>The type representing that set is called class wide.
>
>Since "class" equates with "type", class-wide type is meaningless.

Because an ISO standard says so? You know, Ada 95 is an ISO standard too [ISO/IEC 8652:1995(E)]. Always troubles with that standards ... (:-))

>>>"Most-specific type", 'declared type" and "inherited type" have meaning.
>>
>>How many types has the value 1, provided that I can derive from
>>integer?
>
>Integer is rational is real is complex.

So only 4 types. What if I derive my own type? What if I call my friends to derive a bit more types?

>Natural is whole is integer.
>
>Any others you would like to propose?

Lots. The file descriptor for instance. 1 is stdout.

>>>>>>A specific Circle is not an instance of Ellipse. It is an instance of
>>>>>>Circle.
>>>>>
>>>>>An instance is not a value -- it is a variable.
>>>>
>>>>No. An instance of a type is a value of that type.
>>>
>>>Values do not change -- ever. Do instances? Instances are variables.
>>
>>Instance of a type is a value
>
>Incorrect. Instance of a type is a variable of the type.
>
>>Instance of a generic function is a function
>
>Functions change.

In C++: template <int X> int foo () is a generic function. Its instance when X=5 is a regular function.  

>>Instance of a generic type is a type
>
>A parameterized variable of a generic type.

In C++ template <int X> class Y {...} is a generic type. Its instance is a regular type Y<5>.

>>Instance of a task type is a task
>
>Tasks change.

?

>The value 10^(10^(10^(10^(10^(10^(10)))))) existed even before I represented
>it and even though I have no numeric variable in which to store its value.

Did it exist even when arabic notation was not yet invented? (:-))

>>To have a value (point it, pass it etc) one should have a variable
>>that holds it.
>
>One could have a literal or a constant.

Literal can be viewed as a read-only variable. Both literals and constants might require elaboration (construction) if they have some complex types.

>>You are trying to say that behind every value there is
>>an ideal, abstract value existing outside the language, the soul of a
>>value, so to say. OK, let it be so. It is irrelevant.
>
>It is relevant to the user of the DBMS.

I meant irrelevant to the programming language.

>>>>They are well distinguished in any language.
>>>
>>>If that is so, why does C++ have any difficulty implementing the very
>>>natural subtype/supertype relationship between circle and ellipse?
>>
>>Because LSP [+definition of property] is formulated so, that it is
>>impossible.
>
>Sorry, but you are putting the cart before the horse. If we apply LSP to
>values of ellipses and values of circles, we see that it is not only
>possible but entirely desirable.

Value of an ellipse cannot be resized because the result [in most cases] is another value. Surely there would be no problem with LSP if all operations violating it are removed. Guillotine is the best cure of scurf.

>>There are fundamental reasons behind this.
>
>Only because the language makes insufficient distinction between value and
>variable.

[...]

>>You pointed the distinction: values are immaterial and enjoy
>>witnessing of the God of programming. Variables are sinful and
>>condemned forever. (:-)) Seriously why in your opinion, say in C++,
>>values and variables are not distinguished?
>
>Update operations necessarily operate only on variables while non-update
>operations necessarily operate only on values, and C++ makes no distinction
>between the two. Constraining a variable to a single value or a subset of
>values is a different matter.

  1. Both update and non-update operations operate on variables
  2. void Foo (const X); is Foo an undate or non-update operation?

>>>>An representation issue is whether the
>>>>tag is embedded in the value or not.
>>>
>>>Physical independence requires that the representation be unimportant to
>the
>>>user, which makes it irrelevant to the discussion at hand.
>>
>>It is very important to the user whether a value is tagged or not.
>
>Believe me: The user could not care less how the DBMS implements
>polymorphism as long as it works.

There is no dynamic polymorphism without tags. So being non-existing it would not work, which should wake up some interest of the user.

>>>Your statement that a circle value is not an ellipse does not change the
>>>fact that it is. Conversion is unecessary.

>>
>>Here is a proof:
>
>Bullshit. That was no proof.

Very convincing. Give your proof that in a language we both know one cannot distinguish values of the base type from the values of one of its subtypes.

>>>>-1 is not
>>>>double
>>>
>>>I disagree. In a poorly designed language, it might not be. But -1 is a
>>>valid value for a double precision floating point number. -1 is a valid
>>>rational and real.
>>
>>-1 is a literal of integer type. Or are you arguing that -1 belongs to
>>the set of real numbers? That is also true. But those -1s are
>>different ones.
>
>In my language, -1 is a literal of real type also.

Then they are two different literals overloaded in some given context. One -1 has the type Integer another -1 is Real. A more OO-ish technique is simply to inherit literals. And all literals are considered as parameterless function returning the literal value.

>>>Should we not discuss whether Abs(x) is legal or whether Magnitude(x) is
>>>legal instead? Why should we introduce type-specific names for the
>operation
>>>when we can assume polymorphism?
>>
>>fabs is not polymorphic [unfortunately it is impossible in C++].
>
>fabs is not object oriented -- it exists in C, which says nothing about C++
>and nothing about the topic of discussion.

How a routine can be object oriented or not? Isn't it a property of a programming language?

>>>>How the compiler would distinguish them?
>>>
>>>The DBMS knows and understands its internals. How would it not?
>>
>>Here is a contradiction. You say that representation is not an issue
>
>It is not an issue to the user because the principle of physical
>independence prohibits the DBMS from exposing any detail of the
>representation to the user.
>
>>and immediately propose to distinguish types by their represenation.
>
>I have stated exactly the opposite -- you are the one who proposed different
>representation-based types. Please do not put words in my mouth. I am quite
>capable of doing that myself.

But you said that "DBMS knows and understands" some "internals" and so it is able to distinguish types. [Is "internals" an ISO equivalent of "representation"?] So I made the conclusion you argued that the representation determines the type. Or it is the type that determines the representation. In any case, to distinguish types by representation there should be a mapping representation->type. This excludes multiple type representations.

>>>>If they are distinguishable, then
>>>>why not to call them [sub]types?
>>>
>>>If they are indistinguishable to the user, why not call them the same
>type?
>>
>>They are same. Consider it as an axiom: "If two types are
>>undistinguishable they are same. If two types are not same then either
>>one is a subtype of another or they are unrelated."
>
>I can accept that provided we accept that representation is orthogonal to
>type.

It is, in the sense that a user/compiler is free to choose a representation for a type. But the choice shall be made. So there are two mappings: type->representation to have an ability to create a value of a type, and [necessary for the class wide values only] represenation->type to have dispatch possible.

>>>>Different types?
>>>
>>>Nope. Different representations of the same type.
>>
>>Remember, you said that representation determines the type.
>
>Hell no! Two floating point numbers do not a complex make!
>
>>Either the
>>type determines the representation [my point]
>
>Type constrains the possible representations but does not necessarily
>determine representation.

There should be a defined representation to have values of a type. Value is a language term here.

>Not my point. My point is: Type does not determine representation and
>representation does not determine type.

Then you should explain how dispatch can work, if there is not way to determine the type.

>>>For instance, the DBMS
>>>might allow both cartesian and polar representations of complex numbers.
>The
>>>user should not have to care which representation any given variable
>stores
>>>at any given time. The operations and values are equivalent regardless of
>>>the representation used.
>>
>>It is easy to achive. Derive polar complex from cartesian one and make
>>it both a sub- and supertype. Here you are.
>
>Your example does not achieve the desired result. Complex is a single type
>regardless of the physical representation.

Why? I can use both different complex types interchangeable. It is all that we need, or?

>>>>So you naturally
>>>>come a cristal clear idea: a value has a type.
>>>
>>>Yes. Ane one naturally comes to the crystal clear idea that a type has
>>>multiple equivalent representations.
>>
>>In which sense equivalent?
>
>The imaginary unit has two equivalent representations: cartesian and polar.
>The representation does not change the value nor the value's type.

A value having one representation can be converted to the value having another representation. It does not make the types of those values same. It only establish a subtype relation between them.

>>How do I distinguish that representations?
>
>If the user wants to know the polar representation, the user queries the
>magnitude and phase (or angle) attributes of the complex number. If the user
>wants to know the cartesian representation, the user queries the real-part
>and imaginary-part attributes of the complext number.
>
>At no time should the DBMS reveal to the user which representation a given
>complex variable contains.

But DBMS knows and distinguishes that represenations? Then there should be some additional information (tag) that identifies the representation. Now consider that the representation-new is that tag + all what you call multiple representations. This representation-new is same for all values of a type. So we can say that a type has exactly one representation.

>>And how do you call the set of all values having exactly one [of that
>>multiple] representation. I would call it a type. And you?
>
>I call it the empty set. All of the values have both representations.

Simultaneously? So the representations are undistinguishable = same.

>>>>A type has an implementation.
>>>
>>>I disagree. It has multiple implementations. There are more than one way
>>>to skin a cat, after all.
>>
>>Again, there should be a construct behind an implementation [among
>>many].
>
>Physical independence requires the DBMS to allow as many implementations as
>are required.
>
>>It seems that you have no name for that.
>
>I call it physical representation or storage.
>
>>My proposal to you is
>>to consider the following naming convention (used in Ada). What you
>>call "type" [with multiple representations] is a class-wide type. What
>>you have no name for, is a normal type.
>
>My proposal to you is to consider the generally accepted naming conventions.
>What you call a "class-wide type" is the set of specific types that a
>variable of a declared type can contain -- either directly or through
>inheritance.

Is that the generally accepted convention that a variable contains a set of types? What is the difference between containing directly or through inheritance? I find it a bit confusing.

>What you claim I have no name for is an abstract data type. (See ISO/IEC
>2382-15.04.02)

Sorry, but abstact types have no values => representation.

>>>>It is actually what subtyping is for. Isn't it?
>>>
>>>No. Subtyping is for subtypes not equivalent representations of the same
>>>type.
>>
>>Equivalent in what sense. You claimed that representation is not an
>>issue for types [I completely agree with that], hence for subtypes
>>too. Whether a type is a subtype shall be representation-independed.
>
>A complex number with cartesian representation (0,1) is eqivalent to and
>equal to a complex number with polar coordinates (1,Degrees(90)).

For any value of ComplexCartesian and any value of ComplexPolar there are corresponding complex numbers. For some values they are the same number. So what? This does not make ComplexCartesian the set of complex numbers.

>>>>class Circle : public RosaElephant, public Ellipse {...}
>>>>
>>>>You cannot pass such circle to an ellipse method without conversion.
>>>
>>>In the specific implementation of your compiler, perhaps, but that says
>>>nothing about subtypes and supertypes in general.
>>
>>In which compiler it could be possible?
>
>In any compiler that fully supports polymorphism.

How it supposed to work, provided that according to you values of Circle are values of RosaElephant and simultaneously of Ellipse?

>>>>>It could be done without any conversion at all. In fact, physical
>>>>>independence almost requires it.
>>>>
>>>>This
>>>>
>>>>1. Exposes representation, because it requires that a subtype have
>>>>same representation as the base.
>>>
>>>No, it does not. It requires that the DBMS understand how to operate on
>>>different representations of the same type without conversion, and it
>>>requires that the DBMS understand how to operate on subtypes without
>>>conversion.
>>
>>Let it understand, but how it could operate?
>
>Using operations. What makes you think it could not?

It sees values and all those values are same. Which operation should it use?

>>>>2. Eliminates multiple inheritance.
>>>
>>>Again, it does not. You are confusing unecessary implementation details
>with
>>>essential aspects of the problem.
>>
>>Representation is indeed an implementation detail, so I do not want
>>the representation of a subtype be limited.
>
>Good. You agree with the principle of physical independence.

I always been.

Regards,
Dmitry Kazakov Received on Sun Sep 02 2001 - 16:30:29 CEST

Original text of this message