Re: Clean Object Class Design -- Circle/Ellipse

From: Dmitry A. Kazakov <dmitry_at_elros.cbb-automation.de>
Date: Sat, 01 Sep 2001 21:26:47 GMT
Message-ID: <3b913737.1293936_at_news.cis.dfn.de>


On Fri, 31 Aug 2001 22:11:11 -0400, "Bob Badour" <bbadour_at_golden.net> wrote:

>>>You've lost me here. What exactly am I mixing? A value is a value.
>>
>>Yes, and any value has a type.
>
>Any value has multiple types: its most-specific type and all of its
>inherited types.

We disagree here. Any value has exactly one type.

>>>>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. The term "class" is used for a set of types derived from a given one. The type representing that set is called class wide. The values of that type are class wide values.

>"Most-specific type", 'declared type" and "inherited type" have meaning.

How many types has the value 1, provided that I can derive from integer?

>>>>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
Instance of a generic function is a function Instance of a generic type is a type
Instance of a task type is a task
...

>Consider: Values exist regardless of whether any representation currently
>exists for them in the universe. The value 5 exists even if it appears
>nowhere in your application or your computer at some point in time.

It is a pure phylosophical argument, however if you interested to know I do not support Plato's theory. So it does not work for me. 5 is just a set of shining dots appearing to be on my screen which by the way does not exist together with that dots because I am an inveterate solipsist. (:-))

>>A variable of some
>>given type may hold values (instances) of that type.
>
>This is a common misconception. A reference to a variable of some given type
>refers to a specific variable (instance) of that type.

In short, reference to a variable refers to a specific variable. That's true.

>An instance (variable) of some given type may hold values of that type.

>Variables have identity. Instances have identity. Values are identity.
>(Values are self-identifying, if you prefer.)

Yes, values are states. Variables have states = values.

>One can have pointers to an instance. One can have pointers to a variable.
>One cannot have pointers to a value because self-identifying values exist
>independent of representation. (One can point to a representation of 5, but

>one cannot point to 5.)

I'd put it so, values do not exist without variables [in a language]. To have a value (point it, pass it etc) one should have a variable that holds it. 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.

>>>I agree that Circle
>>>variables are not Ellipse variables and vice-versa. The same is true of
>any
>>>subtype variable and supertype variable, which is why I think well-thought
>>>languages must clearly distinguish between variable and value.
>>
>>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. There are fundamental reasons behind this. C++ is bad, but for LSP there is no cure. This is why I am against LSP.

>>More important is that
>>one should distinguish between readonly (in) and full access (inout,
>>out) variables.
>
>I disagree. Constraints on variables are nowhere near as fundamentally
>important as a distinction between the very different concepts of 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?

>>>>In contrary to this both a class-wide Circle and a class-wide
>>>>Ellipse are instances of Ellipse'Class [not Ellipse!]. A class-wide
>>>>value consists of the type tag indicating the type and the value of
>>>>that type [In C++ the type tag is allways in the value, which leads to
>>>>confusion].
>>>
>>>Values have no type tags -- they just are. All of the above are simply
>>>implementation issues and are ultimately irrelevant to the discussion at
>>>hand -- as is the rest of your example.
>>
>>Disagree. Values of class-wide types always have a tag associated with
>>them.
>
>Again, you are confusing things by introducing undefined, unecessary new
>terminology. "class-wide type" is meaningless.
>
>The "tag" to which you refer is an implementation detail. Obviously, the
>DBMS must know both the type and the representation of that type in use at
>any given moment. Whether the DBMS implements this with a tag is irrelevant
>to the discussion of type inheritance.

This is the key issue for inheritance and dispatch. To know the representation one should know the type. The type can be known either statically or at run time. In the later case there should be a tag to indicate the type.

>>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. No tag - no dispatch. No dispatch - no overriding.

>>>Your example did nothing to address the statement that a circle value, no
>>>matter the representation, is an ellipse. It has all the properties of an
>>>ellipse.
>>
>>My point is that a circle value is not an ellipse. It mimics an
>>ellipse, because there is a defined conversion to ellipse.
>
>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:

class Ellipse
{
public :

   virtual void WhoAreYou () { printf ("I am an ellipse"); } };
class Circle : public Ellipse
{
public :

   virtual WhoAreYou () { printf ("I am NOT an ellipse"); } };

Circle ().WhoAreYou ();

As you see the computer is able to distingush circles from ellipses. q.e.d.

>>-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.

>>yet fabs (-1) is legal.
>
>I thought we were discussion object oriented languages.
>
>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++]. It is inherited by int from double. This is an example why conversions are necessary.

>>>One must have at least one possible representation for every type, and one
>>>can have several. This does not require any type conversion.
>>
>>It would be to complex to have several representation for a type.
>
>Says you. The principle of physical independence requires it. Deal with it.
>
>
>>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 and immediately propose to distinguish types by their represenation.

>>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."

>>Different types?
>
>Nope. Different representations of the same type.

Remember, you said that representation determines the type. Either the type determines the representation [my point], then several types may have same representation [=abstraction], or [your point] the representation determines the type, which is IMO hard to defend.

>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.

>>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? How do I distinguish that representations? 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?

>>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]. It seems that you have no name for that. 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.

>>Multiple representations/implementations can be easily
>>achived via subtyping.
>
>At the cost of confusion and additional work for the user. We in the
>database world do not accept that cost.
>
>>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.

>>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?

>>>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?

>>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.

Regards,
Dmitry Kazakov Received on Sat Sep 01 2001 - 23:26:47 CEST

Original text of this message