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
Le 07/07/2021 à 14:32, Brent Roose a écrit :
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
orHasUuid
or something alike. This interface would probably require its implementers to expose agetUuid(): 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 usingpublic 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
Hello,
I agree, properties in interfaces would be very useful. It would allow
me to get rid of many traits I wrote until now. I can live without it,
but having it would be great help in many use cases I'm confronted with
on a daily basis.
--
Regards,
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 behaviourIdentifiable
orHasUuid
or something alike. This interface would probably require its
implementers to expose agetUuid(): string
method.Without interfaces being able to define properties, we'll now have to
implement agetUuid()
method on all our 10 classes, nullifying the
advantage we got from usingpublic 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
The property accessor RFC (which didn't get to a vote) discussed this, and specifically proposed making properties part of the interface for... basically all the reasons given here.
My preference would be to add property accessors in 8.2 (at least the asymmetric visibility part), and then redefine readonly
properties as a shorthand for a "get only" implicit accessor property; which, if I recall correctly, is essentially the same semantics as readonly
. (I didn't check the RFC; I'm going by memory here.) That would include interface properties by nature.
--Larry Garfield
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 behaviourIdentifiable
orHasUuid
or something alike. This interface would probably require its
implementers to expose agetUuid(): string
method.Without interfaces being able to define properties, we'll now have to
implement agetUuid()
method on all our 10 classes, nullifying the
advantage we got from usingpublic 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 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 <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
<https://docs.swift.org/swift-book/LanguageGuide/Protocols.html https://docs.swift.org/swift-book/LanguageGuide/Protocols.html>The property accessor RFC (which didn't get to a vote) discussed this, and specifically proposed making properties part of the interface for... basically all the reasons given here.
I thought the RFC didn't go to vote because Nikita didn't feel like it warranted the complexity:
This RFC overlaps with the Property Accessors RFC. In particular, it implements the “only implicit get” aspect, though not with the exact same semantics. As mentioned in the RFC, I'm not convinced that the full complexity of accessors is truly warranted. Supporting readonly properties and asymmetric visibility would cover a significant portion of the use-cases, at a lower language complexity cost. [1]
Is there any reason to assume property accessors will be reconsidered for 8.2?
[1] https://wiki.php.net/rfc/readonly_properties_v2#rationale
Kind regards
Brent
My preference would be to add property accessors in 8.2 (at least the asymmetric visibility part), and then redefine
readonly
properties as a shorthand for a "get only" implicit accessor property; which, if I recall correctly, is essentially the same semantics asreadonly
. (I didn't check the RFC; I'm going by memory here.) That would include interface properties by nature.--Larry Garfield
--
To unsubscribe, visit: https://www.php.net/unsub.php <https://www.php.net/unsub.php
The property accessor RFC (which didn't get to a vote) discussed this, and specifically proposed making properties part of the interface for... basically all the reasons given here.
I thought the RFC didn't go to vote because Nikita didn't feel like it
warranted the complexity:This RFC overlaps with the Property Accessors RFC. In particular, it implements the “only implicit get” aspect, though not with the exact same semantics. As mentioned in the RFC, I'm not convinced that the full complexity of accessors is truly warranted. Supporting readonly properties and asymmetric visibility would cover a significant portion of the use-cases, at a lower language complexity cost. [1]
Is there any reason to assume property accessors will be reconsidered for 8.2?
Nothing is guaranteed. :-) However, Nikita said very clearly in the readonly discussion that he doesn't see it as precluding the asymmetric visibility portion of accessors, which is still simpler than full on explicit accessor methods. We "just" have to convince Nikita that upgrading readonly to asymmetric visibility in 8.2 (with or without explicit methods) is justified, and that it should include the interface portion of that, too.
--Larry Garfield
Le 07/07/2021 à 23:16, Larry Garfield a écrit :
The property accessor RFC (which didn't get to a vote) discussed this, and specifically proposed making properties part of the interface for... basically all the reasons given here.
My preference would be to add property accessors in 8.2 (at least the asymmetric visibility part), and then redefine
readonly
properties as a shorthand for a "get only" implicit accessor property; which, if I recall correctly, is essentially the same semantics asreadonly
. (I didn't check the RFC; I'm going by memory here.) That would include interface properties by nature.--Larry Garfield
Using property accessors on interfaces is fine too, but the one thing
that properties directly being defined on interfaces do bring is that
you don't have to repeat implementation of those in your
implementations. That's a detail, but a practical one.
Regards,
--
Pierre