comp.lang.ada
 help / color / mirror / Atom feed
From: John G. Volan <John_Volan@ccmail.dayton.saic.com>
Subject: "Object" types vs. "Value" types
Date: 1996/03/20
Date: 1996-03-20T00:00:00+00:00	[thread overview]
Message-ID: <4inn6f$1at@dayuc.dayton.saic.com> (raw)
In-Reply-To: gauthier-1503961110320001@164.81.60.62

In article <4ih2pv$pku@dmsoproto.ida.org>
David Wheeler, wheeler@aphrodite.csed.ida.org writes:
>Michel Gauthier (gauthier@unilim.fr) wrote:
...
>: Stacks are designed to organise values, not objects. 
>: Stacks are objects, not values.
>
>Not true.  This stack organizes Items. Items might be values, or they might
>be references.  There is no reason to assume they must be one or the other.
>For performance reasons you might choose to stack references instead of
>the actual values, but there's no reason they MUST be one or the other.
...
>: David probably means either stacks of (item=>references to stacks) or
>: stacks of
>: (item=> some implementation of the stack abstract type with an initial algebra
>: behaviour).
>: The latter actual type is an academic feature that has strictly no 
>: practical use.
>
>Disagree; see my example of arrays of arrays.
...

In his book _Object Oriented Analysis and Design With Applications_,
Grady Booch defines an "object" as something which has "state",
"behavior, and "identity." 
    
Booch defines "state" as:

    The state of an object encompasses all of the (usually static)
    properties of the object plus the current (usually dynamic)
    values of each of these properties.
    
Booch quotes Khoshafian and Copeland's definition of "identity":

    Identity is that property of an object which distinguishes
    it from all other objects.
    
The identity of an object is something ineffably linked with that
object, and with that object alone.  Even if two objects are both in
exactly the same state, they are still distinct objects, because their
identities are different. On the flip side, the identity of an object
is that property which never changes, regardless of all the changes of
state that it experiences.

In light of these notions, I long ago came to the conclusion that, as
far as programming was concerned, there was a useful distinction to be
made between two sorts of data types: "object" types and "value"
types. An "object" type is a data type for which the distinction
between "identity" and "state" was strong, whereas a "value" type would
lack this strong distinction.

A "value" can be duplicated in many different locations, and each
instance of that "value" would be considered "identical" to all the
others.  No matter where you saw it, it would be the "same value".

An "object", on the other hand, can occupy only one location, and cannot
be "duplicated" elsewhere, not as such. You might be able to duplicate
the _state_ of an object into another location, but then you wouldn't 
conclude that you then had the "same object" at that new location. 
Rather, you would conclude that there was a _different_ object at that
location, and now that object happened to have the "same state" as
your original object.

At least, for the moment -- the state of an object can change.  Yet even
when that happens, the object doesn't suddenly become a "different
object." It always remains the "same object."  It just goes into
different states at different times.  Those different states might
change its behavior, but it still remains "itself."

Conversely, "values," as such, do not have states that can change.  In a
certain Platonic-ideal sense, a "value" is something eternal and
unchanging. Now, understand what I mean by this:  Let's say for
instance that you see the number 2 at a particular location at a
particular time, and then later see a different number, say 3, at that
location. The value _at_ that location changed, but in no way did "the
number 2" change. The number 2 is still the integer value that follows
1 and precedes 3 -- always has been and always will be.  And the
behavior of "the number 2" never changes, either:  If you add one to
the number 2, you'll always get the number 3, and if you subtract one
from it, you'll always get the number 1.  Always, forever and ever,
world without end, amen.  :-)

What does all this philosophizing have to do with Ada?  Well, IMHO, this
distinction between "objects" and "values" maps quite neatly to the Ada
concept of limited versus non-limited types.  In my view, if you're
going to categorize something as an "object", and invest it with all
the connotations implied by that designation, then by rights the type
ought to be limited.

Assignment just doesn't make sense for an "object" type.  You shouldn't
be able to just "copy" an object willy-nilly -- what would that mean?
Oh, you could copy the _state_ of that object into another object
(write yourself a Copy procedure). Or you could copy the _identity_
('Access) of that object from one (access) variable to another (access)
variable.  But copy the "object" per se?  No, I'd rather shut off
assignment rather than open up that can of worms.  Physical objects in
the real world don't go around being indiscriminately replicated (Star
Trek's replicators are still just a fantasy), so I'd prefer the
"objects" in my software to share the same kind of "solidity."

On the other hand, if you do have a data abstraction for which
assignment makes sense, that's okay too, you can make it non-limited --
I just wouldn't call that an "object" type, I'd call it a "value" type.

Note that there's nothing about this notion of "value" types that
precludes such "object-oriented" concepts as "inheritance" and
"polymorphism" and "type extension" and "dynamic dispatching."  I think
it's perfectly reasonable to talk about having classes of "value"
types, with derived value types inheriting attributes and behavior from
ancestor value types, and adding new attributes and behavior, and so
forth.  "Value" classes can work just like "object" classes -- the only
difference is that assignment is defined for the former but shut off
for the latter.

(Indeed, it's my humble (and perhaps radical) opinion that the very term
"object-oriented" is a misnomer.  The paradigm that everybody is so
gung-ho about these days should have been called "*CLASS*-oriented"
programming.  A programming language could hypothetically give you
_objects_ without necessarily giving you _classes_ as well.  It's the
_classes_, and the relationships between them, that give you all that
juicy inheritance and polymorphism.)

There's also nothing in this "value" concept that precludes the use of
unbounded dynamic data structures or structural sharing.  All of that
is just private implementation details anyway.  The bottom line is that
if you want assignment to be meaningful for your data abstraction, then
the publicly-visible semantics of your abstraction have to be totally
stripped of any notion of unique identity.  If you use assignment to
duplicate a particular "value" to numerous locations, every single
instance of that "value" must behave exactly like every other instance,
without any "identifiable" distinction between them.  If you assign a
"different value" into one of those locations, this should not affect
the behavior of the original value manifested at any of the other
locations. Moreover, if you do any other kind of operation with a side
effect that changes the "value" in one particular variable, none of the
other variables still holding the old value should behave any
differently, even if secretly all those variables were sharing a data
structure. Whatever machinations you have to engage in behind the
scenes in order to achieve these effects doesn't matter, as long as the
semantics of "value" types is maintained as far as clients are
concerned.

Contrast this with a limited "object" type:  You won't be able to use
assignment to copy an "object" to multiple locations, although you
might make multiple copies of an _access value_ that "identifies" that
object. However, if then you perform an operation through one of these
pointers that changes the state of the designated object, then the same
change of state will automatically be observed through all of the other
pointers designating that same object.

Now, as for a particular abstract data type, such as our moldy old
friend, the stack:  Is a stack an "object"?  Or is it a "value"?
"Object"? "Value"? "OBJECT"? "VALUE"? <getting delirious> WELL, IS IT
ONE OR THE OTHER?!?!?!?!?!?!?!?!?

My answer is: FOR GOODNESS SAKES, YES!!!!!!!!!!!     :-)  :-)  :-)

It can be _either_, depending on how you choose to perceive it.  I
believe most folks would tend to view a stack as an "object" (and
that's how I tend to view it myself), on the grounds that the Push and
Pop operations are thought of as having "side-effects."  However, I
admit that one might reasonably argue for a view that interprets a
stack as a "value," by analogy with another "aggregate" abstraction:
the array.

Array types in Ada are non-limited, so you can do assignment on them. 
If two arrays happen to hold the same sequence of element values, then
they're considered to have the same "array value."  By analogy, one
might say that two stacks that contain the same sequence of stacked
element values should be considered as the same "stack value."

My philosophy: Pick whichever semantic scheme best fits your
application, implement it, and be happy.  Just call it by the right
name. :-)

I even reflect that philosophy in my chosen naming style:  I tend to let
the package name carry the sense of an abstraction, and I use some
"nondescript" identifier for the type encapsulated in the package, on
the grounds that everybody should refer to it as "Package.Type" anyway.
Well, "Object" is the nondescript identifier I will pick, if and only
if the type is limited.  "Value" is the nondescript identifier I'll
pick, if and only if the type is non-limited.

So, for example, if a stack is an "object", I'll have:

    generic
        type Item is private;
    package Stack is
        type Object is limited private;
        ...
    end Stack;
    
Otherwise, if a stack is just a "value", I'll have:

    generic
        type Item is private;
    package Stack is
        type Value is private;
        ...
    end Stack;

------------------------------------------------------------------------
Internet.Usenet.Put_Signature
( Name => "John G. Volan", E_Mail => "John_Volan@dayton.saic.com",
  Favorite_Slogan => "Ada95: The *FIRST* International-Standard OOPL",
  Humorous_Disclaimer => "These opinions are undefined by SAIC, so" &
    "any use would be erroneous ... or is that a bounded error now?" );
------------------------------------------------------------------------




  parent reply	other threads:[~1996-03-20  0:00 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <4i6l2t$j1q@dmsoproto.ida.org>
1996-03-15  0:00 ` Comments on generic stack? Michel Gauthier
1996-03-17  0:00   ` David Wheeler
1996-03-20  0:00   ` John G. Volan [this message]
1996-03-20  0:00     ` "Object" types vs. "Value" types John DiCamillo
1996-03-21  0:00       ` Comments on generic stack? John G. Volan
1996-03-21  0:00     ` "Object" types vs. "Value" types david scott gibson
1996-03-25  0:00       ` John G. Volan
1996-03-28  0:00         ` david scott gibson
1996-03-25  0:00 Jean-Pierre Rosen
1996-03-25  0:00 ` Robert Dewar
1996-03-26  0:00 ` Michel Gauthier
1996-03-27  0:00   ` Richard A. O'Keefe
1996-03-27  0:00     ` Robert Dewar
1996-03-27  0:00 ` Michel Gauthier
  -- strict thread matches above, loose matches on Subject: below --
1996-03-26  0:00 Jean-Pierre Rosen
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox