Re: Ada Interfaces and the Liskov Substitution Principle



On Tue, 05 Jun 2007 15:12:29 -0700, Maciej Sobczak wrote:

On 5 Cze, 10:35, "Dmitry A. Kazakov" <mail...@xxxxxxxxxxxxxxxxx>
wrote:

I was talking about access Object'Class with Circle and Triangle being
both derived from Object.

What is the difference between the types access T'Class and T'Class?

Access T'Class can be reseated to point to some other object from
T'Class, even if that other object has different tag.

So what? According to you that is wrong because there exist n*n possible
combinations of such assignments for different tags. In what sense these
combinations are different for T'Class and access T'Class?

In the sense that access T'Class has only one combination to cover and
since access is a fundamental type, this is handled by the language.
You don't have to do anything to make assignment for access T'Class
work!

Hence you agree that when assignment is defined then it is no matter how
many combination of exists. Therefore your argument about the number of
combinations is irrelevant for any user- or compiler-generated assignment.

In our earlier discussion I assumed this obvious, as it follows from
separation of implementation and interface. Anyway, now, when the
implementation is finally left to the problem domain, what is the
*semantic* difference between access T'Class and T'Class beyond that?

No, access Whatever should not be unconditionally limited, otherwise
there would be little justification for its existence in the type
system.
The raison d'etre for access T is the ability to *point* - and be
*reseated*.

While for T'Class it is the ability to accommodate any specific T. Where is
a difference?

In assignment.

Nope, you cannot say that the difference is in assignment, because now we
are talking about "ability to point" and "ability to hold." What makes
"point" different to "hold", semantically I mean?

procedure Swap (X, Y : in out String);

declare
X : String := "abc";
Y : String := "klmnoprst";
begin
Swap (X, Y);
-- oops

OK, even better. Let's ban assignment for all unconstrained types. :-)

My congratulations! But that's not all:

procedure Swap (X, Y : in out Integer);

declare
X : Positive := 1;
Y : Integer := -1;
begin
Swap (X, Y);
-- oops

I hope you see now, why your proposal is inconsistent with any type system
with constrained [sub]types (classes is just a specific case of)? Further,
it is incompatible with specialization and generic programming on sets of
specialized types. It can be easily shown, that it is also incompatible
with generalization and in the end with generic programming on any
non-trivial sets of types.

Why your "fundamental" reasons do not apply here?

The "fundamental" reasons apply here as well. The problem is of a
general nature.

Huh, speaking of general natures, the problem is a misconception shared by
LSP-ers. The issue can be summarized in three lines:

1. Specialization breaks all out-methods of the base type
2. Generalization breaks all in-.methods of the base type
3. Variation breaks everything

The rest is consequences. This cannot be fixed and need not to.

The only truly fundamental reason is that if Object was declared
non-limited, then its contract is to support assignment. It is then the
programmer responsibility to fulfill this contract for Triangle and Circle.
Don't blame the language for your own design faults.

No. Regular objects are declared as Triangles and Circles (and these
types may have reasonable assignments - after all, assigning one
Triangle to another makes sense). The problem is when you declare
something as T'Class.

Wrong. Assignment is a primitive operation <=> it is defined on T'Class.
Specific assignments are irrelevant here.

T'Class /= T and this is one of the things that make them different.
I know that it shakes part of the concept of a class.

Yep, it demolishes class and primitive operations of.

But you have the same problem with unconstrained types. They might not
support all operations of their constrained equivalents.

What does it mean "not support"? You have to translate this into illegal
("type error") / legal ("no type error"). See above, there is no way out.
Either you scrap the type system, by forbidding any intertype relations or
you have to live with the cross cases. In the middle there exists a wide
range of semi-consistent languages like C++ and, alas, Ada.

- constructors cannot be polymorphic, since there is no tag yet (you
might dispatch on something different, though, but this is irrelevant)

There is the tag, it exists before the object and comes from the type of. A
constructor (actually a part of) dispatches on the bare tag.

I don't agree on this.

X : T;
Y : T'Class := Whatever;

Do_Something(X); -- (1)
Do_Something(Y); -- (2)

Which of the two above are dispatching (assume Do_Something is
primitive)?

So? Following your argument destructor of X isn't dispatching either,
because it will not dispatch in this piece of code.

A part of the constructor of T'Class is certainly dispatching. The
constructor of T is specific for T. This makes constructor a primitive
operation. On the other hand, constructors are composed by extension, which
makes them class-wide operations as well (you have to construct T'Class for
a specific S derived from T). This controversy is the reason why
constructors aren't easy to get right. The idea of my proposal was to make
it typed and factor out specific and class-wide parts a constructors as
user-defined subprograms.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
.



Relevant Pages

  • Re: Ada Interfaces and the Liskov Substitution Principle
    ... You don't have to do anything to make assignment for access T'Class ... There is the tag, it exists before the object and comes from the type of. ... constructor dispatches on the bare tag. ... My understanding of the concepts is that only is a dispatching ...
    (comp.lang.ada)
  • Re: Controlled types and exception safety
    ... >> constructor throws/raises, the object is considered to be never created ... you'll have memory leaks and other such badness. ... > actually wish is to have access to the left side of assignment. ... Ada doesn't really have user-defined assignment; ...
    (comp.lang.ada)
  • Re: Copy Constructors and Assignment Operator, When should I use?
    ... ItemSet set1; ... constructor for ItemSet, ItemListA and ItemListB for it works ... plain reference. ... using assignment instead of initialisation), so there is no need to write ...
    (microsoft.public.vc.language)
  • Re: operator=
    ... Compiler will supply - unless the programmer decides to do it - the ... It isn't required in an assignment: ... You will find that the code within the copy constructor and assignment ... Aside from the inlined code [i.e. the member ...
    (alt.comp.lang.learn.c-cpp)
  • Re: Controlled types and exception safety
    ... >> propagate an exception. ... >> For an Adjust invoked as part of an assignment operation, ... But a user-defined constructor is ... a user-defined constructor has just turned on the ...
    (comp.lang.ada)