@property fields
Richard Andrew Cattermole (Rikki)
richard at cattermole.co.nz
Tue Dec 3 23:50:20 UTC 2024
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.
```d
interface IField {
@property int field;
}
class Thing : IField {
@property int field;
}
struct Thing2 {
@property int field;
}
```
It results in three things.
1. A field that is either ``protected`` (classes) or ``private``
(structs).
```d
class Thing : IField {
protected int field;
}
struct Thing2 {
private int field;
}
```
If we have struct inheritance, then it would be ``protected``
instead.
2. It will generate a method for classes and structs in the form:
```d
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;
}
}
```
3. A method stub is generated for the property field in an
interface:
```d
interface IField {
ref typeof(this.field) __property_field();
}
```
You may place attributes around the field to apply to the
method.
```d
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:
1. You will not have direct access to the field outside of the
type. All accesses and mutation will go through the method.
2. It may be passed to a function parameter that is ``ref`` or
``out``. This is perfectly safe so needs no protection due to it
implicitly being ``scope``.
3. An invariant will be called following mutation or when it is
passed to a ``ref`` or ``out`` function
parameter.
3.1. For interfaces if a ``@property`` field is used, an
invariant will be required to be in the vtable implicitly.
4. In ``@safe`` code:
4.1. It may not be stored in a ref variable ``ref 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).
More information about the dip.ideas
mailing list