comp.lang.ada
 help / color / mirror / Atom feed
* Re: Polymorphism/Inheritence
  1997-02-26  0:00 Polymorphism/Inheritence Adam C. Bacon
@ 1997-02-26  0:00 ` Jon S Anthony
  1997-02-28  0:00   ` Polymorphism/Inheritence Stephen Leake
                     ` (2 more replies)
  1997-02-27  0:00 ` Polymorphism/Inheritence Robert Dewar
  1 sibling, 3 replies; 6+ messages in thread
From: Jon S Anthony @ 1997-02-26  0:00 UTC (permalink / raw)



In article <5f0pcc$5b9@news.cps.udayton.edu> abacon@cps.udayton.edu (Adam C. Bacon) writes:

>   type Vehicle is tagged private;
> 
> I also have a pointer declared as follows:
>   type Vehicle_Pointer is access Vehicle'Class;
> 
> In a child package specification, I have a private type declared as follows:
>   type Car is new Vehicle with private;
> 
> I have two local variables defined in the child package body as follows:
>   Pointer  : Vehicle_Pointer;
>   Temp_Car : Car;
> 
> The problem that I have arises when I make an assignment in a function
> defined in the child package body.  The assignment occurs in a Create
> procedure, which is as follows:
>   Pointer.all := Temp_Car;
> 
> Prior to this assignment, I make the following:
>   Pointer := new Car;
> 
> The error which I receive from the compiler is the following:
>   Pointer.all := Temp_Car;
>                  |
>   dynamically tagged expression required

This has something to do with the fact that class wide objects (like
your pointer.all) are dynamically tagged while temp_car is statically
tagged.  But that's not all there is to it.  For one thing, a
statically tagged object used as an actual to a class wide parameter
in a call is first implicitly converted to the class wide type.  The
same thing as happens in:

    X : Vehicle'Class := Temp_Car;

So, the error message here seems irrelevant.  But that's not all.

This seems to be one of those areas in the RM where the more you dig
the less you end up knowing.  We do know that a class wide type (like
the designation of Vehicle_Pointer) is indefinite (here, this means
has unknown discriminants).  We also know that this means that any
object of the type will thus have an actual subtype which is
constrained (by the initial value) and so the object is constrained.

Now, once you have a constrained object you can't change it - or at
least that's what I've long thought and there are several hints in the
RM that this is true (like the notes in 3.7), but I cannot find the
rule which either says this or implies it.  So, this might not
actually be true.  If it is true, then your assignment is really wrong
since it is trying to change a constrained object (this despite the
fact that the discriminant of the actual constrained subtype is the
same as that of Car).

OTOH, 4.6(21,22,52) seems to indicate that maybe you can do this
conversion after all, but you have to give an explicit subtype_mark.
For example, if you change to:

    Pointer.all := Vehicle'Class(Temp_Car);

Now, this compiles and runs OK on GNAT 3.09.  But I don't know if it
is really correct...

/Jon



-- 
Jon Anthony
Organon Motives, Inc.
Belmont, MA 02178
617.484.3383
jsa@organon.com





^ permalink raw reply	[flat|nested] 6+ messages in thread

* Polymorphism/Inheritence
@ 1997-02-26  0:00 Adam C. Bacon
  1997-02-26  0:00 ` Polymorphism/Inheritence Jon S Anthony
  1997-02-27  0:00 ` Polymorphism/Inheritence Robert Dewar
  0 siblings, 2 replies; 6+ messages in thread
From: Adam C. Bacon @ 1997-02-26  0:00 UTC (permalink / raw)



I am a Computer Science student at the University of Dayton using the
GNAT Compiler for Ada 95.  One of our recent problems was to write a
simple set of packages and a driver program to illustrate the principles
of inheritence and polymorphism.  In doing the assignment, I discovered
a difference (which I believe may be a bug) between version 2.06S of
the GNAT compiler (for DOS, using DJGPP) and versions 3.04 and higher.

In my parent package specification, I have the parent type in the
hierarchy declared as a tagged private type:
  type Vehicle is tagged private;

I also have a pointer declared as follows:
  type Vehicle_Pointer is access Vehicle'Class;

In a child package specification, I have a private type declared as follows:
  type Car is new Vehicle with private;

I have two local variables defined in the child package body as follows:
  Pointer  : Vehicle_Pointer;
  Temp_Car : Car;

The problem that I have arises when I make an assignment in a function
defined in the child package body.  The assignment occurs in a Create
procedure, which is as follows:
  Pointer.all := Temp_Car;

Prior to this assignment, I make the following:
  Pointer := new Car;

The error which I receive from the compiler is the following:
  Pointer.all := Temp_Car;
                 |
  dynamically tagged expression required

After discussing this problem with my professor and with other students,
we are unable to find out why this occurs, especially since it does not
occur in GNAT version 2.06S, only in versions 3.04 and higher.  If anyone
else has experienced this problem, I would be interested in discussing
any possible solutions you have found.

Thanks,
Adam Bacon




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Polymorphism/Inheritence
  1997-02-26  0:00 Polymorphism/Inheritence Adam C. Bacon
  1997-02-26  0:00 ` Polymorphism/Inheritence Jon S Anthony
@ 1997-02-27  0:00 ` Robert Dewar
  1 sibling, 0 replies; 6+ messages in thread
From: Robert Dewar @ 1997-02-27  0:00 UTC (permalink / raw)



Adam wondered about:

<<After discussing this problem with my professor and with other students,
we are unable to find out why this occurs, especially since it does not
occur in GNAT version 2.06S, only in versions 3.04 and higher.  If anyone
else has experienced this problem, I would be interested in discussing
any possible solutions you have found.>>

The reason that this clear illegality did not get flagged in GNAT 2.06S is
that 2.06 is a VERY old version of GNAT (well over a year old, and at least
7 versions behind the current release), and it lacked some error checks,
that was one of them!





^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Polymorphism/Inheritence
  1997-02-26  0:00 ` Polymorphism/Inheritence Jon S Anthony
@ 1997-02-28  0:00   ` Stephen Leake
  1997-03-01  0:00   ` Polymorphism/Inheritence Robert Dewar
  1997-03-03  0:00   ` Polymorphism/Inheritence Jon S Anthony
  2 siblings, 0 replies; 6+ messages in thread
From: Stephen Leake @ 1997-02-28  0:00 UTC (permalink / raw)



In article <5f0pcc$5b9@news.cps.udayton.edu> abacon@cps.udayton.edu
(Adam C. Bacon) writes:
> [description of example; replaced with compilable code:]

package Parent is
   type Vehicle is tagged private;
   type Vehicle_Pointer is access Vehicle'Class;
private
   type Vehicle is tagged record
      Maker_ID : Integer;
   end record;
end Parent;

package Parent.Child is
   type Car is new Vehicle with private;

   procedure Create
      (Maker_ID : in Integer;
       Wheels : in Integer);

private
   type Car is new Vehicle with record
      Wheels : Integer;
   end record;
end Parent.Child;

package body Parent.Child is
   Pointer  : Vehicle_Pointer;

   procedure Create
      (Maker_ID : in Integer;
       Wheels : in Integer)
   is
      Temp_Car : Car := (Maker_ID, Wheels);
   begin
      Pointer := new Car;
      Pointer.all := Temp_Car;
   end Create;
end Parent.Child;

> >   Pointer.all := Temp_Car;
> >                  |
> >   dynamically tagged expression required

Jon Anthony replies with an informative discussion of class wide types,
and suggests:

> 
>     Pointer.all := Vehicle'Class(Temp_Car);
> 
> Now, this compiles and runs OK on GNAT 3.09.  But I don't know if it
> is really correct...
> 

This certainly works, and is consistent with the RM, as Jon points out.
This is a view conversion; it does not change the value of Temp_Car as
it copies it. Pointer.all is of type Vehicle'class; this is a different
type than Car, so a view conversion is required. 

However, depending on what Create really does, there are better ways to
do this. For example:

   procedure Create
      (Maker_ID : in Integer;
       Wheels : in Integer)
   is
   begin
      Pointer := new Car'(Maker_ID, Wheels);
   end Create;

This avoids the entire issue, and saves a copy operation. If Create
truly needs a Temp_Car for other reasons, then:

   procedure Create
      (Maker_ID : in Integer;
       Wheels : in Integer)
   is
      Temp_Car : Car'class;  -- error
   begin
      Pointer := new Car;
      ...
      mess with Pointer and/or Temp_Car
      ...
      Pointer.all := Temp_Car;
   end Create;

But class wide objects need initialization, so we try:

   procedure Create
      (Maker_ID : in Integer;
       Wheels : in Integer)
   is
      Temp_Car : Car'class := (Maker_ID, Wheels);
   begin
      Pointer := new Car;
      ...
      mess with Pointer and/or Temp_Car
      ...
      Pointer.all := Temp_Car;
   end Create;

This seems like it should work, but now I get:

      Temp_Car : Car'class := (Maker_ID, Wheels);
parent-child.adb:8:31: aggregate not available for limited array

This is a very weird message, since there are neither arrays nor limited
types present. I'll send it to gnat_report. 

What is this error trying to tell me?
-- 
- Stephe




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Polymorphism/Inheritence
  1997-02-26  0:00 ` Polymorphism/Inheritence Jon S Anthony
  1997-02-28  0:00   ` Polymorphism/Inheritence Stephen Leake
@ 1997-03-01  0:00   ` Robert Dewar
  1997-03-03  0:00   ` Polymorphism/Inheritence Jon S Anthony
  2 siblings, 0 replies; 6+ messages in thread
From: Robert Dewar @ 1997-03-01  0:00 UTC (permalink / raw)



Jon Anthony says

<<    Pointer.all := Vehicle'Class(Temp_Car);

Now, this compiles and runs OK on GNAT 3.09.  But I don't know if it
is really correct...>>

yup, it's correct!





^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Polymorphism/Inheritence
  1997-02-26  0:00 ` Polymorphism/Inheritence Jon S Anthony
  1997-02-28  0:00   ` Polymorphism/Inheritence Stephen Leake
  1997-03-01  0:00   ` Polymorphism/Inheritence Robert Dewar
@ 1997-03-03  0:00   ` Jon S Anthony
  2 siblings, 0 replies; 6+ messages in thread
From: Jon S Anthony @ 1997-03-03  0:00 UTC (permalink / raw)



In article <dewar.857270127@merv> dewar@merv.cs.nyu.edu (Robert Dewar) writes:

> Jon Anthony says
> 
> <<    Pointer.all := Vehicle'Class(Temp_Car);
> 
> Now, this compiles and runs OK on GNAT 3.09.  But I don't know if it
> is really correct...>>
> 
> yup, it's correct!

Right - it occured to me sometime after my post here that constrained
objects can have their _value_ changed, but not their form or
structure.  That's what the notes in 3.7 are really trying to say.
So, my concerns about the "constrainedness" of the object were
irrelevant.

/Jon

-- 
Jon Anthony
Organon Motives, Inc.
Belmont, MA 02178
617.484.3383
jsa@organon.com





^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~1997-03-03  0:00 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-02-26  0:00 Polymorphism/Inheritence Adam C. Bacon
1997-02-26  0:00 ` Polymorphism/Inheritence Jon S Anthony
1997-02-28  0:00   ` Polymorphism/Inheritence Stephen Leake
1997-03-01  0:00   ` Polymorphism/Inheritence Robert Dewar
1997-03-03  0:00   ` Polymorphism/Inheritence Jon S Anthony
1997-02-27  0:00 ` Polymorphism/Inheritence Robert Dewar

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