comp.lang.ada
 help / color / mirror / Atom feed
* How to check class type ?
@ 2021-04-21 17:08 DrPi
  2021-04-21 17:26 ` AdaMagica
  2021-04-21 17:40 ` Dmitry A. Kazakov
  0 siblings, 2 replies; 7+ messages in thread
From: DrPi @ 2021-04-21 17:08 UTC (permalink / raw)


Hi,

I have the following declarations (just for the example) :

type Root is tagged null record;
type Root_Ptr is access all Root'Class;

type Leaf1 is new Root with null record;
type Leaf1_Ptr is access all Leaf1'Class;

type Leaf2 is new Root with null record;
type Leaf2_Ptr is access all Leaf2'Class;


To check if a variable is of type Leaf1_Ptr or Leaf2_Ptr, I do :
if var'Tag = Leaf1'Tag then
    ...
elsif var'Tag = Leaf2'Tag then
    ...
end if;

It works. But is this correct ? Should the test be done differently to 
suit Ada coding style ?

Nicolas

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

* Re: How to check class type ?
  2021-04-21 17:08 How to check class type ? DrPi
@ 2021-04-21 17:26 ` AdaMagica
  2021-04-21 17:33   ` DrPi
  2021-04-21 17:48   ` DrPi
  2021-04-21 17:40 ` Dmitry A. Kazakov
  1 sibling, 2 replies; 7+ messages in thread
From: AdaMagica @ 2021-04-21 17:26 UTC (permalink / raw)


DrPi schrieb am Mittwoch, 21. April 2021 um 19:08:32 UTC+2:
> if var'Tag = Leaf1'Tag then 
> ... 
> elsif var'Tag = Leaf2'Tag then 
> ... 
> end if; 
> 
> It works. But is this correct ?

Why not?

if Var in Leaf1 then
   ...
elsif Var in Leaf2 then

But normally you would use dispatching.
Why do you need this?

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

* Re: How to check class type ?
  2021-04-21 17:26 ` AdaMagica
@ 2021-04-21 17:33   ` DrPi
  2021-04-21 17:48   ` DrPi
  1 sibling, 0 replies; 7+ messages in thread
From: DrPi @ 2021-04-21 17:33 UTC (permalink / raw)


Le 21/04/2021 à 19:26, AdaMagica a écrit :
> DrPi schrieb am Mittwoch, 21. April 2021 um 19:08:32 UTC+2:
>> if var'Tag = Leaf1'Tag then
>> ...
>> elsif var'Tag = Leaf2'Tag then
>> ...
>> end if;
>>
>> It works. But is this correct ?
> 
> Why not?
> 
> if Var in Leaf1 then
>     ...
> elsif Var in Leaf2 then
> 
> But normally you would use dispatching.
> Why do you need this?
> 
I have a Vector which contains pointers to Leaf1/Leaf2 instances.
At some point, I need to know what the cursor points to.

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

* Re: How to check class type ?
  2021-04-21 17:08 How to check class type ? DrPi
  2021-04-21 17:26 ` AdaMagica
@ 2021-04-21 17:40 ` Dmitry A. Kazakov
  2021-04-22  8:50   ` DrPi
  1 sibling, 1 reply; 7+ messages in thread
From: Dmitry A. Kazakov @ 2021-04-21 17:40 UTC (permalink / raw)


On 2021-04-21 19:08, DrPi wrote:
> Hi,
> 
> I have the following declarations (just for the example) :
> 
> type Root is tagged null record;
> type Root_Ptr is access all Root'Class;
> 
> type Leaf1 is new Root with null record;
> type Leaf1_Ptr is access all Leaf1'Class;
> 
> type Leaf2 is new Root with null record;
> type Leaf2_Ptr is access all Leaf2'Class;
> 
> 
> To check if a variable is of type Leaf1_Ptr or Leaf2_Ptr, I do :

That does not make sense, Leaf1_Ptr is not tagged.

> if var'Tag = Leaf1'Tag then
>    ...
> elsif var'Tag = Leaf2'Tag then
>    ...
> end if;


    if Var in Leaf1'Class then
       ... -- Class rooted in Leaf1
    elsif Var in Leaf2'Class then
       ... -- Class rooted in Leaf2

> It works. But is this correct ? Should the test be done differently to 
> suit Ada coding style ?

It depends on the intent. Usually you should never check for the class 
except two cases:

1. Defensive programming of a downcast:

    if X in T'Class then
       declare
          Y : T'Class renames T'Class (X);
       begin
          ...
       end;

Downcasts are by themselves problematic, to be avoided when possible.

2. Emulation of multiple dispatch.

In most cases you leave all tag checks to dispatch.

This may lead to so-called God-classes when primitive operations migrate 
to the root. E.g. if you had a primitive Foo on Leaf1, but not in Leaf2 
and the purpose of check would be if you could call to Foo, you might 
move Foo as abstract to Root and override it as raising exception in 
Leaf2. Then instead of checking for the tag, you would simply dispatch:

    Var.Foo; -- Will raise if not Leaf1

This would be a God-class case.

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

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

* Re: How to check class type ?
  2021-04-21 17:26 ` AdaMagica
  2021-04-21 17:33   ` DrPi
@ 2021-04-21 17:48   ` DrPi
  2021-04-23 16:13     ` John McCabe
  1 sibling, 1 reply; 7+ messages in thread
From: DrPi @ 2021-04-21 17:48 UTC (permalink / raw)


Le 21/04/2021 à 19:26, AdaMagica a écrit :
> DrPi schrieb am Mittwoch, 21. April 2021 um 19:08:32 UTC+2:
>> if var'Tag = Leaf1'Tag then
>> ...
>> elsif var'Tag = Leaf2'Tag then
>> ...
>> end if;
>>
>> It works. But is this correct ?
> 
> Why not?
> 
> if Var in Leaf1 then
>     ...
> elsif Var in Leaf2 then
> 
> But normally you would use dispatching.
Mmmh... Makes me think I did it the wrong way...
I'm a C programmer. I'm afraid I still think as if I where programming in C.
I'll change my code.
Thanks


> Why do you need this?
> 

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

* Re: How to check class type ?
  2021-04-21 17:40 ` Dmitry A. Kazakov
@ 2021-04-22  8:50   ` DrPi
  0 siblings, 0 replies; 7+ messages in thread
From: DrPi @ 2021-04-22  8:50 UTC (permalink / raw)


Le 21/04/2021 à 19:40, Dmitry A. Kazakov a écrit :
> On 2021-04-21 19:08, DrPi wrote:
>> Hi,
>>
>> I have the following declarations (just for the example) :
>>
>> type Root is tagged null record;
>> type Root_Ptr is access all Root'Class;
>>
>> type Leaf1 is new Root with null record;
>> type Leaf1_Ptr is access all Leaf1'Class;
>>
>> type Leaf2 is new Root with null record;
>> type Leaf2_Ptr is access all Leaf2'Class;
>>
>>
>> To check if a variable is of type Leaf1_Ptr or Leaf2_Ptr, I do :
> 
> That does not make sense, Leaf1_Ptr is not tagged.
> 
>> if var'Tag = Leaf1'Tag then
>>    ...
>> elsif var'Tag = Leaf2'Tag then
>>    ...
>> end if;
> 
> 
>    if Var in Leaf1'Class then
>       ... -- Class rooted in Leaf1
>    elsif Var in Leaf2'Class then
>       ... -- Class rooted in Leaf2
> 
>> It works. But is this correct ? Should the test be done differently to 
>> suit Ada coding style ?
> 
> It depends on the intent. Usually you should never check for the class 
> except two cases:
> 
> 1. Defensive programming of a downcast:
> 
>    if X in T'Class then
>       declare
>          Y : T'Class renames T'Class (X);
>       begin
>          ...
>       end;
> 
> Downcasts are by themselves problematic, to be avoided when possible.
> 
> 2. Emulation of multiple dispatch.
> 
> In most cases you leave all tag checks to dispatch.
> 
> This may lead to so-called God-classes when primitive operations migrate 
> to the root. E.g. if you had a primitive Foo on Leaf1, but not in Leaf2 
> and the purpose of check would be if you could call to Foo, you might 
> move Foo as abstract to Root and override it as raising exception in 
> Leaf2. Then instead of checking for the tag, you would simply dispatch:
> 
>    Var.Foo; -- Will raise if not Leaf1
> 
> This would be a God-class case.
> 
Thanks for the explanations. As always, very instructive.

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

* Re: How to check class type ?
  2021-04-21 17:48   ` DrPi
@ 2021-04-23 16:13     ` John McCabe
  0 siblings, 0 replies; 7+ messages in thread
From: John McCabe @ 2021-04-23 16:13 UTC (permalink / raw)


On Wed, 21 Apr 2021 19:48:22 +0200, DrPi wrote:

> Le 21/04/2021 à 19:26, AdaMagica a écrit :
>> DrPi schrieb am Mittwoch, 21. April 2021 um 19:08:32 UTC+2:
>>> if var'Tag = Leaf1'Tag then ...
>>> elsif var'Tag = Leaf2'Tag then ...
>>> end if;
>>>
>>> It works. But is this correct ?
>> 
>> Why not?
>> 
>> if Var in Leaf1 then
>>     ...
>> elsif Var in Leaf2 then
>> 
>> But normally you would use dispatching.
> Mmmh... Makes me think I did it the wrong way...
> I'm a C programmer. I'm afraid I still think as if I where programming
> in C.
> I'll change my code.

The tagged type stuff is really there to support polymorphism, and when 
you have a heterogeneous container, where its contents are objects of, or 
derived from, a base class, then the general idea is that the client 
who's using that container shouldn't care about the exact type of the 
object it's dealing with, it should just call <object>.<subprogram> and 
expect <subprogram> to be there.

While that's all well and good in theory, in practise it's very easy to 
mess up and, as Dmitry says, end up with a base class that defines 
multiple different subprograms where derived classes implement a subset 
of those. In these cases you need to ask yourself where the subclasses 
really do have an "is a" relationship with the base class, or whether 
there is some pattern that you can use, e.g. visitor (https://
www.adacore.com/gems/gem-113-visitor-pattern-in-ada - which, unless I'm 
mistaken, corresponds to Dmitry's comment about multiple dispatch) to 
avoid having to make those checks.

HTH


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

end of thread, other threads:[~2021-04-23 16:13 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-21 17:08 How to check class type ? DrPi
2021-04-21 17:26 ` AdaMagica
2021-04-21 17:33   ` DrPi
2021-04-21 17:48   ` DrPi
2021-04-23 16:13     ` John McCabe
2021-04-21 17:40 ` Dmitry A. Kazakov
2021-04-22  8:50   ` DrPi

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