# [RFC] Package private class

- Thread: https://externals.io/message/79873
- Original archive: https://news-web.php.net/php.internals/79873
- Started by guilhermeblanco@gmail.com on 2014-12-23T00:32:53+00:00
- Messages: 7
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #79873 — guilhermeblanco@gmail.com — 2014-12-23T00:32:53+00:00

URL: https://externals.io/message/79873#79873

Hi internals,

I finalized a new proposal for PHP. It consists into adding support for
package-private classes in the language.

A package private class is basically a class that can only be instantiated
in its declared namespace. This means that you cannot extend, implement or
use a class, interface or trait outside of declared namespace. It can be
referenced outside of the package, but instantiation can only be done there.

Other languages such as Java and C# consider package-private class as a
top-level class without any declared visibility. PHP cannot enforce this as
it would be an incredible BC break, but we can reuse an already declared
keyword "private" to fit this purpose. A class declared without any
visibility modifier is considered "public" and works exactly as it
currently does. The same applies to a class written with "public" keyword
(ie. public class Foo {}).

Most of checks are done at compile time and only instantiation is done at
runtime (the only place I found out it could be done). Performance impact
seems negligible as only one top condition is added during instantiation
bytecode executor.


At this stage I want to collect implementation feedback. Explanation is
done above and the extensive amount of tests self explains what the entire
purpose of this feature is. RFC will be created together with voting once
I'm able to gather some considerations.

Link to PR: https://github.com/php/php-src/pull/947


Cheers,

-- 
Guilherme Blanco
MSN: guilhermeblanco@hotmail.com
GTalk: guilhermeblanco
Toronto - ON/Canada

---

## #79879 — Leigh — 2014-12-23T03:34:11+00:00

URL: https://externals.io/message/79873#79879 · In reply to: #79873

On 23 December 2014 at 00:32, guilhermeblanco@gmail.com
<guilhermeblanco@gmail.com> wrote:
> Hi internals,
>
> I finalized a new proposal for PHP. It consists into adding support for
> package-private classes in the language.
>
> A package private class is basically a class that can only be instantiated
> in its declared namespace. This means that you cannot extend, implement or
> use a class, interface or trait outside of declared namespace. It can be
> referenced outside of the package, but instantiation can only be done there.
>
> Other languages such as Java and C# consider package-private class as a
> top-level class without any declared visibility. PHP cannot enforce this as
> it would be an incredible BC break, but we can reuse an already declared
> keyword "private" to fit this purpose. A class declared without any
> visibility modifier is considered "public" and works exactly as it
> currently does. The same applies to a class written with "public" keyword
> (ie. public class Foo {}).
>
> Most of checks are done at compile time and only instantiation is done at
> runtime (the only place I found out it could be done). Performance impact
> seems negligible as only one top condition is added during instantiation
> bytecode executor.
>
>
> At this stage I want to collect implementation feedback. Explanation is
> done above and the extensive amount of tests self explains what the entire
> purpose of this feature is. RFC will be created together with voting once
> I'm able to gather some considerations.
>
> Link to PR: https://github.com/php/php-src/pull/947
>
>
> Cheers,
>
> --
> Guilherme Blanco
> MSN: guilhermeblanco@hotmail.com
> GTalk: guilhermeblanco
> Toronto - ON/Canada

Hey Guilherme,

Good work, namespace visibility on classes and functions is something
I have been working on over the past few months. The reason I haven't
created an RFC is because I couldn't decide on what "private" and
"protected" should mean for a class or function within a namespace.

To me, a private class can only be instantiated within it's own
namespace (this seems the same as you have defined), but can be
typehinted and used anywhere else.

Maybe I was wrong to try and include "protected" in my own work, as it
caused me the most problems when trying to define what it should mean.
My original feeling was that it should mean it can only be
instantiated in it's own namespace or sub-namespaces.

I also considered a strict "visibility" view, private classes would
not be "visible" outside of their own namespace, and protected would
not be "visible" outside of their own or child namespaces ("visible"
meaning no type hints or usage too).

It is reassuring to see that your approach is the same as my initial
feelings, the accessibility keywords define instantiation usage,
rather than a strict visibility.

I haven't looked at your patch in detail. My PoC code revolved around
comparing the start of class names with the current namespace. Is
yours the same? How do you feel about extending this to functions?

Thank's for the work on this. I wasn't sure I had the willpower to
finish my patch for PHP7, it's nice to see you have the same idea.

Cheers,

Leigh.

---

## #79880 — Leigh — 2014-12-23T03:35:38+00:00

URL: https://externals.io/message/79873#79880 · In reply to: #79879

> On 23 December 2014 at 00:32, guilhermeblanco@gmail.com
> <guilhermeblanco@gmail.com> wrote:
> > […]
> ...

I forgot that all important +1 :)

---

## #79885 — Robert Stoll — 2014-12-23T09:59:01+00:00

URL: https://externals.io/message/79873#79885 · In reply to: #79879

> -----Ursprüngliche Nachricht-----
> Von: Leigh [mailto:leight@gmail.com]
> Gesendet: Dienstag, 23. Dezember 2014 04:34
> An: guilhermeblanco@gmail.com
> Cc: PHP internals
> Betreff: Re: [PHP-DEV] [RFC] Package private class
> 
> 
> > […]
> 
> Hey Guilherme,
> 
> Good work, namespace visibility on classes and functions is something I have been working on over the past few months.
> The reason I haven't created an RFC is because I couldn't decide on what "private" and "protected" should mean for a class
> or function within a namespace.
> 
> To me, a private class can only be instantiated within it's own namespace (this seems the same as you have defined), but
> can be typehinted and used anywhere else.
> 
> Maybe I was wrong to try and include "protected" in my own work, as it caused me the most problems when trying to
> define what it should mean.
> My original feeling was that it should mean it can only be instantiated in it's own namespace or sub-namespaces.
> 
> I also considered a strict "visibility" view, private classes would not be "visible" outside of their own namespace, and
> protected would not be "visible" outside of their own or child namespaces ("visible"
> meaning no type hints or usage too).
> 
> It is reassuring to see that your approach is the same as my initial feelings, the accessibility keywords define instantiation
> usage, rather than a strict visibility.
> 
> I haven't looked at your patch in detail. My PoC code revolved around comparing the start of class names with the current
> namespace. Is yours the same? How do you feel about extending this to functions?
> 
> Thank's for the work on this. I wasn't sure I had the willpower to finish my patch for PHP7, it's nice to see you have the
> same idea.
> 
> Cheers,
> 
> Leigh.
> 
> --
>  

[Robert Stoll] 

Hey Guilherme,

I like the idea but I am not sure whether it is wise to define private in the way you did, namely that such classes can be seen outside of its namespace. You referenced Java, which behaves differently for instance. Classes not defined public are only visible in the same namespace. C# classes with "internal" are visible in other namespaces but only within the same assembly (correct me if I am wrong).

I would think of private classes in PHP as Java has implemented them hence they are not visible outside of its namespace. Why? I think one specifies private classes if he/she wants to hide the concrete implementation to others and hence it does not make sense IMO that it can be used as type hint outside. One should use the corresponding interface instead. Therefore, I believe it promotes better code style if we do not restrict the visibility to instantiation only. I think a private class should not be visible at all to others (cannot be used as type hint either).

Yet, I would prefer something like C#'s internal - defining that a certain class is only visible within my own project (can still not be seen by others), but that does not seem feasible right now since PHP has not an assembly like structure. But, just as an idea which just popped into my head, maybe we could introduce something as follows as well (clearly another RFC - but might affect how we define private classes):

namespace ch.tutteli.foo{
   public for ch.tutteli.bar, ch.tsphp*
   private class Foo{}
}

Syntax should not matter, can be changed respectively. The idea would be, that we can define a class private (only visible within its own namespace) but can give access to it by specifying "public for" clauses - in the above example the class Foo would also be visible within the namespace ch.tutteli and within the namespace ch.tsphp as well as its sub-namespaces (denoted by the * at the end)

Maybe it would make sense to introduce a protected modifier as well which means, it is visible along the namespace tree - visible within the same namespace as well as its sub-namespaces and parent namespaces (this would fit with protected as access modifier of members).
However, this would be another RFC of course but we should consider such ideas before deciding what private classes mean in PHP.

Cheers,
Robert

---

## #79886 — guilhermeblanco@gmail.com — 2014-12-23T14:52:00+00:00

URL: https://externals.io/message/79873#79886 · In reply to: #79885

Hi Robert,

Answers inline.



>
>
> > […]
> guilhermeblanco@gmail.com> wrote:
> > […]
> instantiation can only be done there.
> > […]
> have been working on over the past few months.
> > […]
> "private" and "protected" should mean for a class
> > […]
> namespace (this seems the same as you have defined), but
> > […]
> caused me the most problems when trying to
> > […]
> in it's own namespace or sub-namespaces.
> > […]
> be "visible" outside of their own namespace, and
> > […]
> namespaces ("visible"
> > […]
> feelings, the accessibility keywords define instantiation
> > […]
> comparing the start of class names with the current
> > […]
> functions?
> > […]
> finish my patch for PHP7, it's nice to see you have the
> > […]
> visit: http://www.php.net/unsub.php
>
> [Robert Stoll]
>
> Hey Guilherme,
>
> I like the idea but I am not sure whether it is wise to define private in
> the way you did, namely that such classes can be seen outside of its
> namespace. You referenced Java, which behaves differently for instance.
> Classes not defined public are only visible in the same namespace. C#
> classes with "internal" are visible in other namespaces but only within the
> same assembly (correct me if I am wrong).
>

I understand how C# and Java define class visibility and even inside of PR
I mentioned that (
https://github.com/php/php-src/pull/947#discussion_r21542750 ).

I would think of private classes in PHP as Java has implemented them hence
> they are not visible outside of its namespace. Why? I think one specifies
> private classes if he/she wants to hide the concrete implementation to
> others and hence it does not make sense IMO that it can be used as type
> hint outside. One should use the corresponding interface instead.
> Therefore, I believe it promotes better code style if we do not restrict
> the visibility to instantiation only. I think a private class should not be
> visible at all to others (cannot be used as type hint either).
>

Please remember that Java supports 4 levels of visibility on nested classes
and only 2 on top level classes.
What I added support is basically the 2 top level class visibility
supported, since PHP does not allow nested classes.
For top level classes, the allowed visibilities are public and
package-private. Public classes can be instantiated anywhere in the code. I
was forced to make this default in PHP to keep BC, which brought me the
decision on how to classify package-private. I used private because there's
no other semantical meaning when talking about top-level classes.


>
> Yet, I would prefer something like C#'s internal - defining that a certain
> class is only visible within my own project (can still not be seen by
> others), but that does not seem feasible right now since PHP has not an
> assembly like structure. But, just as an idea which just popped into my
> head, maybe we could introduce something as follows as well (clearly
> another RFC - but might affect how we define private classes):
>
> namespace ch.tutteli.foo{
>    public for ch.tutteli.bar, ch.tsphp*
>    private class Foo{}
> }
>
> Syntax should not matter, can be changed respectively. The idea would be,
> that we can define a class private (only visible within its own namespace)
> but can give access to it by specifying "public for" clauses - in the above
> example the class Foo would also be visible within the namespace ch.tutteli
> and within the namespace ch.tsphp as well as its sub-namespaces (denoted by
> the * at the end)
>

That would add a lot of overhead IMHO to library developers, since now
you'd be required to specify who and where classes are allowed. That would
demand tons of runtime checks, which is definitely a no-go since it may
hurt performance a lot.

Maybe it would make sense to introduce a protected modifier as well which
> means, it is visible along the namespace tree - visible within the same
> namespace as well as its sub-namespaces and parent namespaces (this would
> fit with protected as access modifier of members).
> However, this would be another RFC of course but we should consider such
> ideas before deciding what private classes mean in PHP.
>

I thought a lot about protected class support too. But when drafting my
original proposal, I started to ask myself how feasible it would be to
support only declared and sub-namespaces. In reality, dependencies between
sibling namespaces under same vendor name is not a breakage in modeling, so
protected made zero sense to me.
I decided to research around other language implementations but saw nothing
that applied to top level classes.

You can come up with a plan outside of my proposal (or as an enhancement of
my proposal if accepted), but I would keep implementation as is for now
until acceptance phase if none finds a problem on how I tackled this
support.


>
> Cheers,
> Robert
>
>


-- 
Guilherme Blanco
MSN: guilhermeblanco@hotmail.com
GTalk: guilhermeblanco
Toronto - ON/Canada

---

## #79889 — Stanislav Malyshev — 2014-12-23T18:34:00+00:00

URL: https://externals.io/message/79873#79889 · In reply to: #79885

Hi!

> 
> namespace ch.tutteli.foo{ public for ch.tutteli.bar, ch.tsphp* 
> private class Foo{} }

This looks like a recipe for totally unmaintainable situation, where
each class has its own list of places where it is visible, and the lists
are different for each class. I can kind of get when the people want a
class that is not visible to other code. But if it's not the situation,
just use regular class.

I don't think PHP needs arcane rules of class visibility that will be
used by 0.001% of users and even those would probably use it wrong since
there's no way to keep all those individual lists in sync.

-- 
Stas Malyshev
smalyshev@gmail.com

---

## #79890 — Robert Stoll — 2014-12-23T19:43:12+00:00

URL: https://externals.io/message/79873#79890 · In reply to: #79889

> -----Ursprüngliche Nachricht-----
> Von: Stanislav Malyshev [mailto:smalyshev@gmail.com]
> Gesendet: Dienstag, 23. Dezember 2014 19:34
> An: Robert Stoll; 'Leigh'; guilhermeblanco@gmail.com
> Cc: 'PHP internals'
> Betreff: Re: AW: [PHP-DEV] [RFC] Package private class
> 
> Hi!
> 
> > […]
> 
> This looks like a recipe for totally unmaintainable situation, where each class has its own list of places where it is visible, and
> the lists are different for each class. I can kind of get when the people want a class that is not visible to other code. But if it's
> not the situation, just use regular class.
> 
> I don't think PHP needs arcane rules of class visibility that will be used by 0.001% of users and even those would probably
> use it wrong since there's no way to keep all those individual lists in sync.
> 
> --
> Stas Malyshev
> smalyshev@gmail.com
> 

One common place where you actually want such a feature is when you write unit-tests for such a private class which you do not want to place into the same namespace. But I agree, the ch.tphp* example is probably going too far.

Cheers,
Robert
