rfc:friend-classes
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
rfc:friend-classes [2016/01/07 19:57] – mdwheele | rfc:friend-classes [2018/07/14 12:52] (current) – vote end mdwheele | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== PHP RFC: Class Friendship ====== | ====== PHP RFC: Class Friendship ====== | ||
- | * Version: 0.2 | + | * Version: |
- | * Date: 2015-12-10 | + | * Date: 2017-09-21 |
* Author: Dustin Wheeler, mdwheele@ncsu.edu | * Author: Dustin Wheeler, mdwheele@ncsu.edu | ||
- | * Status: | + | * Status: |
* First Published at: http:// | * First Published at: http:// | ||
===== Introduction ===== | ===== Introduction ===== | ||
- | Class Friendship allows a class to be better encapsulated by granting per-class access to protected | + | Class Friendship allows a class to be better encapsulated by granting per-class access to protected |
- | A common use-case for friendship here is separating presentation concerns from what would otherwise be a "tell don't ask" behavioral unit or write model. This can be applied in a variety of scenarios. Without this feature, developers are left with a trade-off of marking internal | + | A common use-case for friendship here is separating presentation concerns from what would otherwise be a "tell don't ask" behavioral unit or write model. This can be applied in a variety of scenarios. Without this feature, developers are left with a trade-off of marking internal |
- | The purpose of the feature should not be conflated or confused with the goals of something like package-private classes or namespace visibility, in general. I feel those features apply more closely to the types of behaviors user-land sees in Symfony (and other framework) packages that mark properties | + | The purpose of the feature should not be conflated or confused with the goals of something like package-private classes or namespace visibility, in general. I feel those features apply more closely to the types of behaviors user-land sees in Symfony (and other framework) packages that mark members |
===== Proposal ===== | ===== Proposal ===== | ||
- | Support for class friendship is added through a new keyword, '' | + | Support for class friendship is added through a new keyword, '' |
==== Basic Usage ==== | ==== Basic Usage ==== | ||
- | A subject class may declare another class a friend through the use of a new '' | + | A subject class may declare another class a friend through the use of a new '' |
- | C++ implements Class Friendship such that friends have access to both private and protected | + | C++ implements Class Friendship such that friends have access to both private and protected |
Below, a class '' | Below, a class '' | ||
Line 59: | Line 59: | ||
{ | { | ||
// HumanResourceReport would not have access to protected | // HumanResourceReport would not have access to protected | ||
- | // properties | + | // members |
return $this-> | return $this-> | ||
} | } | ||
Line 237: | Line 237: | ||
=== Access due to friendship is inherited === | === Access due to friendship is inherited === | ||
- | A friend of '' | + | A friend of '' |
<code php> | <code php> | ||
Line 286: | Line 286: | ||
==== Errors ==== | ==== Errors ==== | ||
- | In all cases above, error messages received are no different than if an object attempted to read or write private or protected | + | In all cases above, error messages received are no different than if an object attempted to read or write private or protected |
==== Additional Thoughts ==== | ==== Additional Thoughts ==== | ||
Line 300: | Line 300: | ||
===== Proposed PHP Version(s) ===== | ===== Proposed PHP Version(s) ===== | ||
- | This proposal targets | + | I had intended to target |
===== RFC Impact ===== | ===== RFC Impact ===== | ||
==== To Opcache ==== | ==== To Opcache ==== | ||
This is an open issue pending code review. I am unfamiliar-enough with Opcache implementation to be able to appropriately assess impact. | This is an open issue pending code review. I am unfamiliar-enough with Opcache implementation to be able to appropriately assess impact. | ||
- | |||
- | ==== To Reflection API ==== | ||
- | New methods are added to '' | ||
- | |||
- | - '' | ||
- | - '' | ||
- | |||
- | ===== Open Issues ===== | ||
- | ==== Policy ==== | ||
- | * Implementation requires code review to advise on improvements as well as inform that Opcache was appropriately considered | ||
- | * Verify current PHP functionality around class property visibility is undisturbed | ||
- | |||
- | ==== Reflection API ==== | ||
- | * Implement new methods on '' | ||
===== Future Scope ===== | ===== Future Scope ===== | ||
While this RFC specifies friendship between classes, there is opportunity to extend this implementation and syntax to include progressive enhancements. Snippets below are hypothetical implementations, | While this RFC specifies friendship between classes, there is opportunity to extend this implementation and syntax to include progressive enhancements. Snippets below are hypothetical implementations, | ||
- | ==== Friendship to global functions | + | * **Friendship to global functions**\\ A class may declare a global function as friend. This might be used if someone wanted to expose a procedural interface to an existing object model or begin to refactor a procedural model to become a façade over a new object model. Modeling best-practice aside, it functions much like standard class friendship. |
- | A class may declare a global function as friend. This might be used if someone wanted to expose a procedural interface to an existing object model or begin to refactor a procedural model to become a façade over a new object model. Modeling best-practice aside, it functions much like standard class friendship: | + | * **Friendship to class methods**\\ Friendship to class methods is a narrower expression of standard class friendship. Instead of declaring the entire class a friend, we declare that a method from a friended class can access the subject' |
+ | * **Friendship to namespace(s)**\\ A class might declare an entire namespace as friend. In this way, any class that is part of that namespace would be friended. | ||
- | <code php> | ||
- | class Person | ||
- | { | ||
- | friend fullname; // Syntax is debatable as part of separate RFC. Idea is same. | ||
- | |||
- | protected $first_name = ' | ||
- | protected $last_name = ' | ||
- | } | ||
- | |||
- | function fullname(Person $instance) | ||
- | { | ||
- | return $instance-> | ||
- | } | ||
- | |||
- | $alice = new Person(); | ||
- | var_dump(fullname($alice)); | ||
- | </ | ||
- | |||
- | ==== Friendship to class methods ==== | ||
- | Friendship to class methods is a narrower expression of standard class friendship. Instead of declaring the entire class a friend, we declare that a method from a friend class can access the subject' | ||
- | |||
- | <code php> | ||
- | class Person | ||
- | { | ||
- | friend Report:: | ||
- | |||
- | protected $first_name = ' | ||
- | protected $last_name = ' | ||
- | } | ||
- | |||
- | class Report | ||
- | { | ||
- | private $person; | ||
- | |||
- | public function __construct(Person $instance) | ||
- | { | ||
- | $this-> | ||
- | } | ||
- | | ||
- | public function getFullName() | ||
- | { | ||
- | return $this-> | ||
- | } | ||
- | | ||
- | public function getIdentifier() | ||
- | { | ||
- | return " | ||
- | } | ||
- | } | ||
- | |||
- | $report = new Report(new Person()); | ||
- | |||
- | var_dump($report-> | ||
- | var_dump($report-> | ||
- | </ | ||
- | |||
- | ==== Friendship to namespace(s), | ||
- | A class might declare an entire namespace as friends. In this way, any class that is part of that namespace would be friended. | ||
- | |||
- | ==== Combinations of Class, Class Method and Namespace Friendship ==== | ||
- | Theoretically, | ||
- | |||
- | <code php> | ||
- | namespace Vendor\Internals { | ||
- | class Person | ||
- | { | ||
- | friend __NAMESPACE__, | ||
- | | ||
- | protected $property = ' | ||
- | } | ||
- | | ||
- | class ImplementationDetail | ||
- | { | ||
- | public function touch(Person $instance) | ||
- | { | ||
- | return $instance-> | ||
- | } | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | <code php> | ||
- | class SomeOtherClass | ||
- | { | ||
- | public function touch(Person $instance) | ||
- | { | ||
- | return $instance-> | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | <code php> | ||
- | function some_function(Person $instance) | ||
- | { | ||
- | return $instance-> | ||
- | } | ||
- | </ | ||
- | |||
- | <code php> | ||
- | $person = new \Vendor\Internals\Person(); | ||
- | $detail = new \Vendor\Internals\ImplementationDetail(); | ||
- | $other = new \SomeOtherClass(); | ||
- | |||
- | var_dump($detail-> | ||
- | var_dump($other-> | ||
- | var_dump(some_function($person)); | ||
- | </ | ||
===== Proposed Voting Choices ===== | ===== Proposed Voting Choices ===== | ||
- | This RFC proposes two voting | + | As this RFC adds syntax to the language, a 2/3 majority is required. (see [[voting]]) |
- | | + | Voting starts on 2018-07-06 21:00 UTC and closes on 2018-07-13 21:00 UTC. |
- | | + | |
- | As this is a language change, a 2/3 majority is required for whether to add Friend Classes to PHP. (see [[voting]]) | + | <doodle title=" |
+ | * Yes | ||
+ | * No | ||
+ | </doodle> | ||
===== Patches and Tests ===== | ===== Patches and Tests ===== | ||
- | I have implemented the RFC as described with tests to verify all usage examples above. | + | I have implemented the RFC as described with tests to verify all usage examples above. |
+ | |||
+ | https:// | ||
As this is my first contribution to PHP, it is my opinion that my request should be placed under higher scrutiny and I am completely ready and willing to accept all feedback to improve implementation. | As this is my first contribution to PHP, it is my opinion that my request should be placed under higher scrutiny and I am completely ready and willing to accept all feedback to improve implementation. | ||
Line 459: | Line 343: | ||
* v0.1 - Created | * v0.1 - Created | ||
* v0.2 - Copy-editing. Clarifications. Add more code examples. | * v0.2 - Copy-editing. Clarifications. Add more code examples. | ||
+ | * v0.2.1 - Fix copy+paste error from ReflectionClass documentation regarding trait methods. | ||
+ | * v0.2.2 - Remove voting choice on implementation detail. Remove example of combined future scope syntax. Correct lacking clarity that friendship applies to all protected members, not just properties. | ||
+ | * v1.0.0 - Final draft of RFC before re-opening discussion |
rfc/friend-classes.1452196655.txt.gz · Last modified: 2017/09/22 13:28 (external edit)