Type Inheritance and Topics

2 posts / 0 new
Last post
Offline
Last seen: 7 years 9 months ago
Joined: 11/24/2015
Posts: 4
Type Inheritance and Topics

Hi,

I'm trying to further my understanding of type inheritence in regards to topics.  The system I'm currently working with has data type structure like:

struct A
{
    string objectId;
};

struct B: A
{
    double x;
};

struct C: A
{
    string words;
}

If I have the topic 'MyData' with the registered type of A, can I write struct Bs and Cs to that topic and can I have a reader that will read both struct Bs and Cs off of the same topic?

 Thanks,

bnkelley

Gerardo Pardo's picture
Offline
Last seen: 4 weeks 3 hours ago
Joined: 06/02/2010
Posts: 601

Hi,

Yes and no. Inheritance is not intended as a way to have a single DataWriter send types polymorphically. Rather as a means of type evolution and to provide a way to have multiple DataWriters and DataReaders with different associated type definitons interoperate. Each Endpoint (Writer/Reader) has its own type "fixed" for each EndPoint. The middleware can convert the data appropriately to make it all work.

The basic mechanism is this.

  1. Each DomainParticipant that creates the Topic needs to register the data-type that it will use for the Topic. 
  2. On the network the data will only contain the attributes that correspond to type  registered by the publisher
  3. Each subscriber will "extend" or "truncate" the network data into the type registered by the subscriber.

Therefore if the publishing DomainParticipant (p_DP) registers topic "MyTopic" with type "A" then the data on the wire will only contain the attributes that correspond to type "A".  If the subscribing DomainParticipant (s_DP) registers topic "MyTopic" with type "C" then when the data arrives it will "extend" the "A" data into a "C" object, filling the additional attributes (x and words) with their defaults  (zero for a double and empty string for a string).

Likewise if you have multiple DataWriters in separate DomainParticipants then you can have p_DP1 publish "A", p_DP2 publish "B", and "p_DP3" publish "C". Similarly you could have s_DP1 subscribe "A", s_DP2 subscribe "B", and "s_DP3" subscribe "C".

In this situation s_DP1 will always receive type "A". When data comes from p_DP2 and p_DP3 the additional fields are truncated by the middleware so p_DP still gets A. Similarly s_DP2 will always receive type "B". When data comes from p_DP1 it will have "x" set to zero and when data comes from p_DP3 the additional field "words" will be dropped. And finally s_DP3 will always receive type "C". When data comes from p_DP1 and p_DP2 the extra fields are filled with default values.

So in some cases there is no way for s_DP3 to distinguish whether the sender sent an "A", a "B", or a "C". Unless the application knows these "default values" are invalid and interprets x==0 as "the x data was not sent so it bust be a A, not a B or a C".

However you could define the types differently:

struct A
{
    string objectId;
};

struct B: A
{
    double x; //@Optional 
};

struct C: A
{
    string words; //@Optional
}

With the above definition the extra members are "Optional" so now the mapping to the different programming languages (C++, Java, etc) will be a pointer or reference and you will be able to know the data was not received because the corresponding field will be "null".

The approach is to have each application define/us the types that they have/expect and then have the system make that work. But each specific DataWriter/Reader is defined with a single Type.

If you need to send multiple/different types from single DataWriter, then the approach would be to either define a Union type that captures the different options, or else to use Optional members to indicate some members may not be present. In addition when using Optional members it is recommended that the type is marked with @Extensibility(MUTABLE_EXTENSIBILITY) because this allows the type to be modified even when it appears nested inside other types.

-Gerardo