The @property
attribute has been left in the lurch for quite some time, where only one behaviour related to its return value being of any value.
There are two parts of this proposal, however I am only confident in the first part, fields.
The other is for methods which would give you full control over it.
Syntax is quite simple:
@property int field;
It is valid in interfaces, structs, and classes.
interface IField {
@property int field;
}
class Thing : IField {
@property int field;
}
struct Thing2 {
@property int field;
}
It results in three things.
-
A field that is either
protected
(classes) orprivate
(structs).class Thing : IField { protected int field; } struct Thing2 { private int field; }
If we have struct inheritance, then it would be
protected
instead. -
It will generate a method for classes and structs in the form:
class Thing : IField { protected int field; ref typeof(this.field) __property_field() /* inferred attributes */ { return this.field; } } struct Thing2 { private int field; ref typeof(this.field) __property_field() /* inferred attributes */ { return this.field; } }
-
A method stub is generated for the property field in an interface:
interface IField { ref typeof(this.field) __property_field(); }
You may place attributes around the field to apply to the method.
interface IField { @safe: @property int field; }
This allows an interface to require that a field exists, without defining one. Since it is the stub that gets inherited (which can only be implemented using an
@property
field.
Semantically:
- You will not have direct access to the field outside of the type. All accesses and mutation will go through the method.
- It may be passed to a function parameter that is
ref
orout
. This is perfectly safe so needs no protection due to it implicitly beingscope
. - An invariant will be called following mutation or when it is passed to a
ref
orout
function
parameter.
3.1. For interfaces if a@property
field is used, an invariant will be required to be in the vtable implicitly. - In
@safe
code:
4.1. It may not be stored in a ref variableref var = thing.field;
4.2. It may not have a pointer taken to it&thing.field
As long as the invariant is called after mutation, this covers the use case of setter methods for properties. It cannot be used to transform, but will cause errors. If you need transformation wrapping the field with a struct could introduce such behaviors so need not be provided at this level (although it should be supported with @property
methods).