Re: Clean Object Class Design -- Circle/Ellipse

From: Bob Badour <bbadour_at_golden.net>
Date: Tue, 4 Sep 2001 03:14:31 -0400
Message-ID: <db%k7.787$4M7.136407109_at_radon.golden.net>


Dmitry A. Kazakov wrote in message <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?

The view that any value has one and only one type disallows inherited type, which then disallows supertypes and subtypes.

Any value has a specific type and possibly many inherited supertypes.

>If you define subtype as a subset then all other follows.

I do not define subtype as a subset. A subtype has a subset of the values and a superset of the properties.

>Other people
>are saying that subtype is a LSP subtype with all the consequences. My
>point is that both deinitions are unsatisfactory.

If one properly recognizes the type difference between variables and values, LSP poses no problem. A variable is a reference to a representation of a value, which makes its type different from that of the value whose representation it references.

>>>>>>>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 ISO standard vocabulary definition for "class" simply recognizes that the OO crowd invented a new word for an old concept.

Your additional definition for "class" overloads the term with a confusing new meaning. I suggest we stick with one meaning, and I further suggest we stick with the general meaning used by OO practitioners.

>>>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 ...
>(:-))

ISO/IEC 8652 has relevance in comp.lang.ada but has no relevance in comp.object or in comp.databases.theory

It is already difficult enough trying to find common ground between comp.databases.theory and comp.object. We do not need to make it any more difficult by introducing arbitrary new terminology from other domains -- even from subdomains.

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

File descriptor is neither a subtype nor a supertype of integer. While it uses similar symbols, the properties of a file descriptor, including defined operations, are neither a subset nor a superset of the properties of integer. For instance, what does it mean to add two file descriptors? Substract? Multiply?

Again, I must point out that your example uses an artifact from a non-object oriented system.

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

This makes it a memory address and the contents of memory addresses change. Further, when considered across different compilations, the memory image of the function will change too. Values do not change.

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

Which is just another way of saying that it is a parameterized variable of a generic type.

>>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? (:-))

Yes, and it still exists even though we can never count it.

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

This describes exactly why neither literals nor named constants are values! They are variables constrained to a single value.

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

I do not care about programming languages. I care about data management. Users care about values, which makes value relevant to programming languages and to data management.

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

One cannot resize an ellipse value because values do not change -- ever. One can resize an ellipse variable because variables do change.

>Surely there would be no problem with LSP if
>all operations violating it are removed.

We have no need to remove any operations. We need only properly recognize the type of values. The type of a variable is a reference to the representation of a value, and the type of the variable is different from the type of the value.

Operations like setFoci operate on variables and not on values.

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

...in C++... which is why I say that C++ makes insufficient distinction between variable and value.

>2. void Foo (const X); is Foo an undate or non-update operation?

...in C++... it is impossible to say, because C++ makes insufficient distinction between variable and value:

  1. Foo could update a global or static variable.
  2. Foo could be a member function that updates the variable referenced by "this".
  3. Foo could be a non-update operation, in which case it performs little of enduring use.

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

Try to think out of the box a little. It is possible -- you just haven't imagined all of the possibilities.

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

One can always determine whether a subset contains a given value. This does not prove whether a conversion is necessary as you claimed. Since a subtype value is also a supertype value, the DBMS can operate on it as the supertype without conversion.

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

Nope. A single literal has multiple types.

>One -1 has the type Integer another -1 is Real.

Nope. The single literal has both type Integer and type Real.

>A more OO-ish
>technique is simply to inherit literals. And all literals are
>considered as parameterless function returning the literal value.

This is an arbitrary and ultimately irrelevant implementation detail. One could just as easily implement all literals as unnamed constants.

In my books, a literal is any literal token or the result of any operation all of whose arguments are literals.

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

If one assumes that the scope of object orientation is limited to programming languages, then anything discussed about object orientation is a property of a programming language. Some people have proposed extending the scope of object orientation beyond programming hoping to apply it to database management.

In either case, discussing a function from a non-object oriented language like C says nothing about object orientation.

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

I see where the confusion comes in. ISO equates "internal level" with physical representation of information. Type and representation are both metadata, and the DBMS must internally represent the metadata information somehow.

In a DBMS, we have a physical design separate from a logical design and separate from dbms internals. A physical design could involve multiple possible representations for a given type. For instance, one can represent complex numbers in cartesian or polar coordinates. Both physical representations represent the same type, and the DBMS can use either representation interchangeably without any logical consequences to the user. The cartesian representation has derived properties for magnitude and angle, while the polar representation has derived properties for real and imaginary parts.

A DBA would interact with and manipulate the physical design without always requiring detailed knowledge of internals -- just as a casual user would interact with the logical design without requiring knowledge of the physical design.

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

Type does not determine representation. Physical representation does not determine type. Internally, the dbms must represent the metadata information regarding type and representation, but does not expose this internal representation to any user. This allows multiple representations for the same type.

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

You assume that a single choice will be made, but the assumption is false. In order to provide physical independence, the dbms must allow multiple representations for a type.

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

You need to think outside the box a little more: there are many more possibilities.

Consider: The dbms might choose an access path today that involves one representation of a domain. The same dbms might choose a different access path tomorrow that involves a different representation of a domain. The same dbms might choose a third access path next week that uses whatever representation it finds stored.

All three examples involve one form of dynamic dispatch or another, but the dbms only needs to track type on an instance by instance basis for the third example. Even in the third example, the dbms might not need any kind of tag because it might be able to derive the type a different way.

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

There must be at least one defined representation to have values of a type, but this does not preclude multiple representations.

>Value is a language term here.

What language? What is wrong with the generally accepted definition? How does the definition as a "language term" differ?

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

Dispatch is ultimately an irrelevant implementation detail when discussing logical type inheritance. A DBMS might derive the type any number of ways just as it might derive the representation any number of ways.

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

We need a single type. The user must be able to declare variables just by specifying Complex. The user must be able to discover the defined properties and operations from the system catalog by specifying a single type, Complex.

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

The abstract or logical interface determines type -- not the physical representation. One can convert from one representation to another without changing type.

>It only establish a subtype relation between them.

No subtype relationship exists because they are the same type. They have exactly the same values and exactly the same properties, including operations.

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

Internally, yes, it must.

>Then there
>should be some additional information (tag) that identifies the
>representation.

Internally, there might be, or there might not be. This is ultimately an internal implementation issue that can change with varying circumstances, and as such is irrelevant to the discussion at hand.

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

Yes. At the logical level, the cartesian representation of Complex(0,1) is indistinguishable from polar representation of Complex(1,Degrees(90)).

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

Assuming polymorphism, it is generally accepted convention that a variable contains a value drawn from a set of types.

>What is the difference between containing directly or
>through inheritance? I find it a bit confusing.

A variable can contain any value whose specific type is the same as the variable's declared type. A variable can contain any value whose specific type inherits the variable's declared type through type inheritance.

You can omit the "directly or through inheritance" phrase from the original sentence without losing any meaning if you find it 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.

Sorry, but the definition for abstract data type only requires us to describe the interface separately from the physical representation. It does not require abstract data types to have no representation. (See ISO/IEC 2382-15.04.02)

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

All values have equivalent representations in both cartesian and polar coordinates.

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

Why would it not work? Variables of RosaElephant can have any value of Circle as well as any other value of RosaElephant. Variables of Ellipse can have any value of Circle as well as any other value of Ellipse. Variables of Circle can have any value of Circle.

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

It should use the operation whose parameters most closely match the specific types of its arguments. Received on Tue Sep 04 2001 - 09:14:31 CEST

Original text of this message