Extra Providence Features
Providence has some extra features that not only does not work in standard thrift, it will break thrift syntax, or the thrift compiler in some way.
Interfaces
Thrift does not have the concept of interfaces, but providences does. Interfaces are declared as any other struct is, but does not support assigning field IDS.
Interfaces has two main uses, being implemented by a struct, and used by a union for generality. E.g.:
```thrift idl interface Person { required string name; }
struct Employee implements Person { 1: required string name; 2: required i32 employee_id; 3: optional double salary; }
struct Customer implements Person { 1: required i32 customer_id; 2: required string name; 3: optional i32 purchases; }
union Entity of Person { 1: optional Employee employee; 2: optional Customer customer; }
This contains two struct each implementing the Person interface.
Note that the two uses a different field ID for the required 'name'
field. The interface type will generate an interface or abstract class
in the languages that support this, and essentially only be validated
as having common fields otherwise. This will generate:
- The `Person` interface with the common `getName()` and `hasName()`
methods.
- The `Employee` and `Customer` message classes will inherit or extend
the `Person` interface. This is equivalent to the `java.implements`
annotation, but is completely encompassed in providence.
- The `Entity` union has more edits. It will have an `asPerson()` method
that returns the current union field as the `Person` interface. And it
will mirror all the methods of `Person` (that it itself implements) and
forward these calls to the current union value. Note that a `union .. of`
requires that **all** fields implements the given interface.
## Circular Containment
This feature is not explicitly supported or not in thrift, but does not
work well in Apache Thrift, meaning that a single struct may contain a
field of it's own type, but you may not have two structs each containing
the other. This is simply a result of the way Apache Thrift parses the
thrift file.
In `providence` you may have circular containment if (and only if) all
of the types referring to each other is in the same thrift definition
file. E.g.:
- struct A contains struct B contains struct A.
```thrift
namespace java net.morimekta.test.calculator
enum Operator {
IDENTITY = 1,
ADD,
SUBTRACT,
MULTIPLY,
DIVIDE
}
union Operand {
1: Operation operation;
2: double number;
}
struct Operation {
1: Operator operator;
2: list<Operand> operands;
}
This makes model structures like the calculator possible. Since the model objects are immutable and created with builders, it is not possible to create a circular instance containment.
Service Sub Methods
Services also support service stub methods, which are declared in a similar
fashion to protobuf
, meaning it will only be declared with a
request and response struct (both must be structs), and no individual parameter
fields.
```thrift idl struct MyRequest { 1: optional string request_field; }
struct MyResponse { 1: optional string response_field; }
service MyService { MyResponse myMethod(MyRequest); }
This is structurally equivalent to declare the request struct's fields
as the method parameters, but may generate different interfaces for
using it:
```thrift idl
struct MyResponse {
1: optional string response_field;
}
service MyService {
MyResponse myMethod(1: optional string request_field);
}