Inheritance in RAPID-ML
In fact, RAPID-ML has experimental support for inheritance at the language level. This works as expected in most cases, creating subtypes in generated code and Swagger-OpenAPI 2.0, using the RAPID-XChange Contract generator.
Using inheritance in combination with realization has some additional code generation semantics. Specifically, each realization of a given data structure should generate a parallel hierarchy of subtypes. This is planned, but not implemented in the current code generators.
Creating Subtypes
The extends keyword on a data structure declaration allows both single and multiple inheritance. Here's a single inheritance example:
structure Person taxpayerID : string lastName : string firstName : string otherNames : string* structure USCitizen extends Person stateOfResidence : string numDependents : int
Restricting Subtypes
RAPID-ML also supports a restrict keyword that can be used to specialize inherited properties, like this:
structure Person taxpayerID : string lastName : string firstName : string otherNames : string* structure USCitizen extends Person restrict taxpayerID: string! of length 9 stateOfResidence : string numDependents : int structure TaxFiling filingID : string! taxpayer : reference to Person! jurisdiction : string year : gYear period : int currency : string grossIncome : decimal taxLiability : decimal structure USTaxFiling extends TaxFiling restrict taxpayer : reference to USCitizen! restrict year : gYear! restrict period : int!
Here, we see a few different uses of restrict:
- Primitive Type Constraints:
The USCitizen subtype restricts taxpayerID to a string with exactly 9 characters. - Subtype Constraints
USTaxFiling restricts taxpayer to the USCitizen subtype. - Cardinality Constraints
USTaxFiling also restricts year and period to be required, by using the ! suffix after the data type.
As you can see, restrict can create a subclass that isn't substitutable using normal inheritance in a strongly-typed language like C# or Java. You would need to use something like generics to capture the pattern. There are other patterns we can apply, depending on the target language.
We allow this because these kinds of covariant, derived-by-restriction relationships are so common in the real world. And we want RAPID-ML's conceptual data modeling to be as natural and expressive as we can make it, even if we incur some extra complexity in mapping it to certain programming languages. We are exploring different ways to express restricted subtypes, and we will offer these as options in our RAPID-ML code generators.