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
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.
On 23 December 2014 at 00:32, guilhermeblanco@gmail.com
guilhermeblanco@gmail.com wrote:...
...
I forgot that all important +1 :)
-----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 classHi 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/CanadaHey 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
Hi Robert,
Answers inline.
-----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 classOn 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/CanadaHey 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.
--
To unsubscribe,
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
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
-----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 classHi!
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
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