Readonly properties and interfaces
| From: | Brent Roose | Date: | Wed, 07 Jul 2021 12:32:49 +0000 |
| Subject: | Readonly properties and interfaces | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-115344@lists.php.net to get a copy of this message | ||
Hi internals
With the readonly properties RFC almost certainly accepted, I'd like to discuss an idea
that's slightly related to them.
One of the problems that readonly properties solve is that they reduce the overhead of writing
getters and setters. This is especially noticeable in objects that hold lots of data — data
transfer objects, value objects, entities. And while public readonly properties will be a style of
programming that not everyone likes, it's clear from the vote on the readonly RFC, as well as
the community feedback, that it's a feature wanted by many.
That brings me to interfaces: currently we're only allowed to define methods on interfaces;
historically this makes sense, since interfaces are meant to define behaviour, and not the
implementation. Most OO language define behaviour using methods, and state using properties, which
in turn are used to define the implementation.
But now, readonly properties are added.
Suddenly, class properties aren't just used for state anymore, they are also used to expose
that state in an immutable way to the outside, where we'd use public getters (behaviour) and
private properties (state) in the past, we can now combine them as public readonly properties.
Wouldn't that imply that there are at least some cases where interface properties could also
make sense?
A simple example:
Imagine we've got 10 different classes that share some behaviour: they are identifiable by a
UUID. Next, imagine we've got a function that can specifically work with all classes that have
a UUID. Proper OO teaches us to write an interface for this behaviour
Identifiable or
HasUuid or something alike. This interface would probably require its implementers to
expose a getUuid(): string method.
Without interfaces being able to define properties, we'll now have to implement a
getUuid() method on all our 10 classes, nullifying the advantage we got from using
public readonly string $uuid in the first place. If, on the other hand, this
functionality was supported, we could write our interface like so, and wouldn't have to worry
about any more boilerplate code:
```
interface HasUuid
{
public readonly string $uuid;
}
```
With the addition of readonly properties, now seems like a good time to discuss changing these
rules. I realise these questions touch the core ideas of OO, so I reckon some people might have
another opinion and I'd like to hear your thoughts.
To give you some more reading material, there is a precedent for interface properties in other
languages:
- TypeScript supports them [1]
- C# supports them, albeit using property accessors [2]
- Swift supports them via Protocols [3]
Looking forward to hearing your thoughts.
Kind regards
Brent
[1] https://www.typescriptlang.org/docs/handbook/type-compatibility.html
<https://www.typescriptlang.org/docs/handbook/type-compatibility.html>
[2] https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/interface-properties
<https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/interface-properties>
[3] https://docs.swift.org/swift-book/LanguageGuide/Protocols.html
<https://docs.swift.org/swift-book/LanguageGuide/Protocols.html>