I don't have my Ada compiler handy, so I'll have to do this from memory (sorry if any syntax errors creep in). Anyhow, let me see if I can explain myself better, starting off with your declarations of:|
Type Shape is abstract tagged null record
Type P1 is access Shape
Type P2 is access Shape'class
and adding some subclasses to this:
Type Circle is new Shape with null record
Type P3 is access Circle
Type P4 is access Circle'class
Now, as you indicate P1 can only point to a shape (and P3 can only point to a circle). This means that from the standpoint of polymorphism, they aren't of much use. A variable of type P1 can only point to an exact instance of type Shape - a var of type P1 could not point to a subclass such as circle. Along similar lines, a function parameter of type P1 must be a pointer to an instance of type Shape - no provision for an instance of a subclass of Shape.
If we look at the record itself, Type Shape, things are only slightly better. Although polymorphism works on function parameters for any subclass, you still have the problem of variables. A variable of Type Shape can not hold an instance of a variable of Type Circle. The variable confines the specific instance of the class to be a match. This forces you into a situation that if you have a variable that must not distinquish the exact type of subclass, you can't store the value as a Type Record - it must be an accessor - specifically a Shape'class accessor.
Which leaves us with access Shape'class as the type of variable used to hold instances of subclasses when the specific instance of the subclass is irrelevant. Any variable which must be capable of polymorphically holding any subclass instance, must use a classwide accessor.
But that leaves us with a different problem: The types Shape'class and Circle'class can not be used interchangeably. This makes it difficult to use the classwide types as parameter types for the functions. If I declare the param type as Circle'class for the circle objects, I can not directly call that function using a variable of type Shape'class from a routine that wants to remain ignorant about the specific subclass instance. But I can't use a Shape'class type for the param since it won't allow access to Circle specific attributes.
Bottom line is this: Variables which need to be capable of holding different subclasses must be a classwide accessor (Shape'class). However, the parameters (and return values) in the functions within the defined classes will only work polymorphically if they operate on the tagged type (not the access pointer types).
My complaint is that Ada'95 does not retain a hierarchy for classwide accessors. In the immediate case, I can not use access Shape'class (P2) and access Circle'class (P4) interchangeably. In other words, the classwide accessors do not behave polymorphically wrt classwide accessors defined in the super or subclasses.