On Fri, May 8, 2026 at 2:42 PM Max Semenik <[email protected]> wrote:
> On Thu, Apr 30, 2026 at 5:10 PM Larry Garfield <[email protected]> > wrote: > >> class User { >> friend UserFactory; >> >> public friend(set) string $name; >> } >> >> class UserFactory { >> public function makeUser($name) { >> $u = new User(); >> $u->name = $name; // This is OK, because UserFactory is a friend. >> return $u; >> } >> } > > > This seems like an overcomplication, in current PHP this would work just > fine: > > class User { > public function __construct( > public readonly string $name, > ) {} > } > > Some of C++ OOP features have always felt like kludges to me, and > friendships are a good example. A well-written class shouldn't care what > other classes are using it, as long as they respect its contract. > > -- > Best regards, > Max Semenik > That example works for users with just a name, but what about users with both a name and user id, with the class invariant that the user with the given name has that specific ID? A class like ``` class User { public function __construct( public readonly string $name, public readonly int $id, ) {} } ``` means that the requirement is on *callers* to get it right, on pain of breaking a whole bunch of things that assume the user id and username correspond to the same record. And while you could do that, it makes it a lot easier to break things. Instead, you would want to have the constructor private. But then, how to create new instances of the User class when you have properly looked up the user id and name in the database? You could add a public static method on User, which would be able to call the constructor, but static methods present other complications with dependency injection and unit testing. And once you move to a separate UserFactory, you wind up with the original issue this seeks to address - how can UserFactory interact with the internals of the User class. Other than making those internals public (which we don't want to do) the only option is to use reflection (which is generally frowned upon). Hence, the proposal to add friends. -Daniel
