Morning All,
https://wiki.php.net/rfc/anonymous_classes
I'd like to hear thoughts regarding the addition of anonymous
classes, patch included.
Cheers
Joe
https://wiki.php.net/rfc/anonymous_classes I'd like to hear thoughts regarding the addition of anonymous
classes, patch included.
I am having a hard time picturing a real-world use-case for this.
-Rasmus
2013/9/23 Rasmus Lerdorf rasmus@lerdorf.com
https://wiki.php.net/rfc/anonymous_classes I'd like to hear thoughts regarding the addition of anonymous
classes, patch included.
I am having a hard time picturing a real-world use-case for this.
The use case is one-time usage of an "implementation", where you currently
probably pass callbacks into a "Callback*"-class like
$x = new CallbackFoo(function() {
/* do something */
});
vs.
$x = new Foo () {
public function doSometing()
{
/* do something */
}
});
Imagine you have several abstract methods in one interface/class, which
would need several callbacks passed to the constructor.
Also '$this' is mapped to the right objects.
Regards,
Sebastian
-Rasmus
--
2013/9/23 Rasmus Lerdorf rasmus@lerdorf.com
https://wiki.php.net/rfc/anonymous_classes I'd like to hear thoughts regarding the addition of anonymous
classes, patch included.
I am having a hard time picturing a real-world use-case for this.
The use case is one-time usage of an "implementation", where you currently
probably pass callbacks into a "Callback*"-class like$x = new CallbackFoo(function() { /* do something */ });
vs.
$x = new Foo () { public function doSometing() { /* do something */ } });
Imagine you have several abstract methods in one interface/class, which
would need several callbacks passed to the constructor.
Also '$this' is mapped to the right objects.Regards,
Sebastian
It also avoids usage of these classes outside the scope where they are
defined...
I'm not sure that I like it yet, since the only use cases so far are very
weird edge cases in my strange experiments.
Surely needs stronger use cases first...
Marco Pivetta
https://wiki.php.net/rfc/anonymous_classes I'd like to hear thoughts regarding the addition of anonymous
classes, patch included.
I am having a hard time picturing a real-world use-case for this.
It is a widely used pattern in object oriented programming:
$subject->attach(new class implements SplObserver {
function update(SplSubject $s) {
printf("Got update from: %s\n" $subject);
}
);
I'd rather go for a new BaseType
syntax, though:
$subject->attach(new SplObserver() {
function update(SplSubject $s) {
printf("Got update from: %s\n" $subject);
}
);
--
Regards,
Mike
https://wiki.php.net/rfc/anonymous_classes I'd like to hear thoughts regarding the addition of anonymous
classes, patch included.
I am having a hard time picturing a real-world use-case for this.
It is a widely used pattern in object oriented programming:
... where you code against interfaces (was supposed to follow that words :))
Sorry.
--
Regards,
Mike
This RFC misses one very important part: an argument for why this
feature is useful. Syntax changes are likely to be extremely contentious
and without convincingreasoning why we need this, we shouldn't even
consider looking at an RFC.
cheers,
Derick
2013/9/23 Derick Rethans derick@php.net
This RFC misses one very important part: an argument for why this
feature is useful. Syntax changes are likely to be extremely contentious
and without convincingreasoning why we need this, we shouldn't even
consider looking at an RFC.
I use anonymous classes very frequently in Java and in C#, and I would say
that they are quite useful. However the examples given in the RFC are
really bad ones. Why on earth would you need a constructor for an anonymous
class? Anonymous classes are used to implement quickly some interface.
Frankly, constructors are not part of any interface. Besides a constructor
is totally useless in an anonymous class as it will never be called after
the object is created.
Let's not rule out this feature yet. It's just a weak RFC, so let's wait
for better approaches.
Lazare INEPOLOGLOU
Ingénieur Logiciel
Lazare Inepologlou linepogl@gmail.com schrieb:
I use anonymous classes very frequently in Java and in C#, and I would say
that they are quite useful. However the examples given in the RFC are
really bad ones. Why on earth would you need a constructor for an anonymous
class? Anonymous classes are used to implement quickly some interface.
Frankly, constructors are not part of any interface. Besides a constructor
is totally useless in an anonymous class as it will never be called after
the object is created.
The need for anonymous classes in Java mostly comes from implementing
interfaces on demand due to the lack of lamdas and the requirements of
a strongly typed language. PHP has lambdas and it doesn't require you
to match typing. Therefore I think the preferred way for most of the
use cases is to use a lambda or if a bigger implementation is necessary,
to give it a name. Due to namespacing you don't pollute the global scope
anyway. Therefore I don't see much reason left as to why add anonymous
classes and I really have a hard time finding a use case, except for trying
to write PHP as you would write Java (which most likely is a bad idea).
- David
2013/9/24 David Soria Parra dsp@php.net
Lazare Inepologlou linepogl@gmail.com schrieb:
I use anonymous classes very frequently in Java and in C#, and I would
say
that they are quite useful. However the examples given in the RFC are
really bad ones. Why on earth would you need a constructor for an
anonymous
class? Anonymous classes are used to implement quickly some interface.
Frankly, constructors are not part of any interface. Besides a
constructor
is totally useless in an anonymous class as it will never be called after
the object is created.The need for anonymous classes in Java mostly comes from implementing
interfaces on demand due to the lack of lamdas and the requirements of
a strongly typed language. PHP has lambdas and it doesn't require you
to match typing. Therefore I think the preferred way for most of the
use cases is to use a lambda or if a bigger implementation is necessary,
to give it a name. Due to namespacing you don't pollute the global scope
anyway. Therefore I don't see much reason left as to why add anonymous
classes and I really have a hard time finding a use case, except for trying
to write PHP as you would write Java (which most likely is a bad idea).
There are many use cases where anonymous classes are useful, even in the
presence of lambdas. I use them quite often when dealing with graphical
interfaces and templates. Here is an example:
abstract class MyFancyHtmlListView extends UI {
protected function IsHeaderVisible(){ return true; }
protected function GetListItemMenu(){ return null; }
protected function OnItemClick( $item ){ }
protected abstract function RenderListItem( $item );
public function Render(){
// echo ...
}
}
With anonymous classes we could do something like this:
<?= new MyFancyHtmlListView(){
protected function IsHeaderVisible(){
return false;
}
protected function RenderListItem( $item ){
// echo ...
}
} ?>
The biggest advantage is that a missing RenderListItem could be statically
verified.
It is just a pattern that follows a different way of thinking: Instead of
having a list of parameters (including lambdas), we have standard methods
that take advantage of all the nice properties of OOP such as abstraction,
inheritance and polymorphism.
Lazare INEPOLOGLOU
Ingénieur Logiciel
Playing devil's advocate here, could this feature make the language more
expressive?
Take for example an API where you'd typically wrap a method call in
try/catch blocks to handle the various "outcomes" e.g. a user login, you'd
maybe have a UserDisabled exception, a UserAlreadyLoggedIn exception, a
UserPasswordIncorrect exception, etc.
With the addition of this syntactic sugar, the method could instead accept
an anonymous class with a onDisabled, onLoggedIn, onPasswordIncorrect
methods.
Perhaps it would also have a performance benefit over cascading through
catch blocks? Though someone else would have to confirm that.
On Tue, Sep 24, 2013 at 8:25 AM, Terence Copestake <
terence.copestake@gmail.com> wrote:
Playing devil's advocate here, could this feature make the language more
expressive?Take for example an API where you'd typically wrap a method call in
try/catch blocks to handle the various "outcomes" e.g. a user login, you'd
maybe have a UserDisabled exception, a UserAlreadyLoggedIn exception, a
UserPasswordIncorrect exception, etc.With the addition of this syntactic sugar, the method could instead accept
an anonymous class with a onDisabled, onLoggedIn, onPasswordIncorrect
methods.Perhaps it would also have a performance benefit over cascading through
catch blocks? Though someone else would have to confirm that.
Why wouldn't you want this to a concrete, real class? I don't see the
benefit, in your example, of doing an anonymous class vs defining an actual
class and passing that in as the handler.
On Tue, Sep 24, 2013 at 8:25 AM, Terence Copestake <
terence.copestake@gmail.com> wrote:Playing devil's advocate here, could this feature make the language more
expressive?Take for example an API where you'd typically wrap a method call in
try/catch blocks to handle the various "outcomes" e.g. a user login, you'd
maybe have a UserDisabled exception, a UserAlreadyLoggedIn exception, a
UserPasswordIncorrect exception, etc.With the addition of this syntactic sugar, the method could instead accept
an anonymous class with a onDisabled, onLoggedIn, onPasswordIncorrect
methods.Perhaps it would also have a performance benefit over cascading through
catch blocks? Though someone else would have to confirm that.Why wouldn't you want this to a concrete, real class? I don't see the
benefit, in your example, of doing an anonymous class vs defining an actual
class and passing that in as the handler.
People express themselves in different ways ...
It is mostly just about expressing the same thing in different ways, we
can find justification for it when pushed, because we are being pushed ...
I'm a bit confused by this idea that every RFC has to be accompanied by
a long list of use cases, expressing ideas that cannot conceivably be
expressed any other way ... that doesn't make any sense, you can do
almost anything a bunch of ways ...
I think enough use cases have been provided, it's an established, widely
used, part of OO elsewhere: The only question is should we have it,
which is incidentally the reason the RFC was sparse in the first place ...
Cheers
-----Original Message-----
From: Joe Watkins [mailto:krakjoe@php.net]
Sent: Tuesday, September 24, 2013 10:08 PM
To: internals@lists.php.net; Kristopher
Subject: Re: [PHP-DEV] RFC: Anonymous ClassesOn Tue, Sep 24, 2013 at 8:25 AM, Terence Copestake <
terence.copestake@gmail.com> wrote:Playing devil's advocate here, could this feature make the language
more expressive?Take for example an API where you'd typically wrap a method call in
try/catch blocks to handle the various "outcomes" e.g. a user login,
you'd maybe have a UserDisabled exception, a UserAlreadyLoggedIn
exception, a UserPasswordIncorrect exception, etc.With the addition of this syntactic sugar, the method could instead
accept an anonymous class with a onDisabled, onLoggedIn,
onPasswordIncorrect methods.Perhaps it would also have a performance benefit over cascading
through catch blocks? Though someone else would have to confirm that.Why wouldn't you want this to a concrete, real class? I don't see the
benefit, in your example, of doing an anonymous class vs defining an
actual class and passing that in as the handler.People express themselves in different ways ...
It is mostly just about expressing the same thing in different ways, we
can
find justification for it when pushed, because we are being pushed ...I'm a bit confused by this idea that every RFC has to be accompanied by a
long list of use cases, expressing ideas that cannot conceivably be
expressed
any other way ... that doesn't make any sense, you can do almost anything
a
bunch of ways ...
[Robert Stoll]
Every syntactic sugar means more overhead for maintaining PHP and therefore
I think it is a good idea to review the idea and ask for real use cases.
However, real use cases were presented in this case which makes sense IMO
and thus I think the RFC should be accepted.
I am not a fan of anonymous classes with lot of logic in it, but small
anonymous classes can be very useful as presented before.
One additional use case I can think of is a composition where it is not
exposed to the outside of the class. An anonymous class extending a small
interface or extending an abstract class with only a few methods seems to be
the suitable candidate here IMO. If PHP would support inner classes I would
probably prefer a private inner class when the anonymous class starts to
hold to much logic.
Cheers,
Robert
I think enough use cases have been provided, it's an established, widely
used, part of OO elsewhere: The only question is should we have it,
which
is incidentally the reason the RFC was sparse in the first place ...Cheers
--
To unsubscribe,
visit:
http://www.php.net/unsub.php
-----Original Message-----
From: Joe Watkins [mailto:krakjoe@php.net]
Sent: Tuesday, September 24, 2013 10:08 PM
To: internals@lists.php.net; Kristopher
Subject: Re: [PHP-DEV] RFC: Anonymous ClassesOn Tue, Sep 24, 2013 at 8:25 AM, Terence Copestake <
terence.copestake@gmail.com> wrote:Playing devil's advocate here, could this feature make the language
more expressive?Take for example an API where you'd typically wrap a method call in
try/catch blocks to handle the various "outcomes" e.g. a user login,
you'd maybe have a UserDisabled exception, a UserAlreadyLoggedIn
exception, a UserPasswordIncorrect exception, etc.With the addition of this syntactic sugar, the method could instead
accept an anonymous class with a onDisabled, onLoggedIn,
onPasswordIncorrect methods.Perhaps it would also have a performance benefit over cascading
through catch blocks? Though someone else would have to confirm that.Why wouldn't you want this to a concrete, real class? I don't see the
benefit, in your example, of doing an anonymous class vs defining an
actual class and passing that in as the handler.People express themselves in different ways ...
It is mostly just about expressing the same thing in different ways, we
can
find justification for it when pushed, because we are being pushed ...I'm a bit confused by this idea that every RFC has to be accompanied by a
long list of use cases, expressing ideas that cannot conceivably be
expressed
any other way ... that doesn't make any sense, you can do almost anything
a
bunch of ways ...[Robert Stoll]
Every syntactic sugar means more overhead for maintaining PHP and therefore
I think it is a good idea to review the idea and ask for real use cases.
However, real use cases were presented in this case which makes sense IMO
and thus I think the RFC should be accepted.
I am not a fan of anonymous classes with lot of logic in it, but small
anonymous classes can be very useful as presented before.One additional use case I can think of is a composition where it is not
exposed to the outside of the class. An anonymous class extending a small
interface or extending an abstract class with only a few methods seems to be
the suitable candidate here IMO. If PHP would support inner classes I would
probably prefer a private inner class when the anonymous class starts to
hold to much logic.Cheers,
RobertI think enough use cases have been provided, it's an established, widely
used, part of OO elsewhere: The only question is should we have it,
which
is incidentally the reason the RFC was sparse in the first place ...Cheers
--
To unsubscribe,
visit:
http://www.php.net/unsub.php
I think sugar can have overhead ... but did you see the patch ??
In this case, there's not really any use cases you can give that
absolutely require anonymous classes, it's personal preference.
I'm glad that others found examples of use cases they can give, as that
seems required ... I just don't really see the sense in saying that's
why we should have it, because absolutely anything suggested can be
achieved without it ...
It's too simplistic, and wrong, to say that all RFC's require the exact
same treatment; they clearly do not. If the idea is simple then the
patch, and ideally the process that gets it merged should also be simple.
Thanks for all the input, everyone, hope this isn't misunderstood ...
Inner classes can be done, I mentioned this in the RFC, there's a patch
to play with, I've not really given it a bunch of thought, so no draft
yet even, I'm just saying, it's a possibility ...
Cheers
I'm growing to like the idea myself. It may create new opportunities for
bad practices, but I don't think it's the concern of internals to police
how people may or may not use a feature. There are also I think a few
things that would need to be addressed before this would be ready for the
real world. For example:
-
As hinted at previously, the "use" statement. Doing this per-method as
suggested would be less ambiguous than applying to the whole class - and
would also prevent pollution. -
Transparency between an anonymous class and the class in which it is
defined (if any). One thing I found very restrictive about closures back in
5.3 was the lack of $this support. I can imagine that missing functionality
being similarly restrictive for these new anonymous classes. Obviously
$this itself will be reserved for use by the anonymous class, which means
there would need to be an alternative. Passing in a variable is one thing,
but as it stands the anon class would then only have public access.
Something like $class with similar behaviour to $this could be an option.
In Java I believe anonymous classes have the same scope as the method in
which they're defined. Would something like this or similar be feasible and
permissible in PHP?
I'm growing to like the idea myself. It may create new opportunities for
bad practices, but I don't think it's the concern of internals to police
how people may or may not use a feature. There are also I think a few
things that would need to be addressed before this would be ready for the
real world. For example:
As hinted at previously, the "use" statement. Doing this per-method as
suggested would be less ambiguous than applying to the whole class - and
would also prevent pollution.Transparency between an anonymous class and the class in which it is
defined (if any). One thing I found very restrictive about closures back in
5.3 was the lack of $this support. I can imagine that missing functionality
being similarly restrictive for these new anonymous classes. Obviously
$this itself will be reserved for use by the anonymous class, which means
there would need to be an alternative. Passing in a variable is one thing,
but as it stands the anon class would then only have public access.
Something like $class with similar behaviour to $this could be an option.In Java I believe anonymous classes have the same scope as the method in
which they're defined. Would something like this or similar be feasible and
permissible in PHP?
-
Anonymous classes in PHP would support a constructor, so I don't see
the need for use to be utilized here, it would just clutter declarations
and the patch. -
Again, constructors can be used, and is less confusing than
introducing a new variable, but I'm open to persuasion if the idea is
liked in general ...
Well, it's likely possible to introduce a shared kind of scope, but I
don't really think it's necessary, for the same reasons as 1) and 2).
- Anonymous classes in PHP would support a constructor, so I don't see
the need for use to be utilized here, it would just clutter declarations
and the patch.
This works, but it's more effort for the programmer and arguably just
moving the "clutter" from the declaration to the constructor.
e.g.
(new class ...
protected $value;
public function __construct($value)
{
$this->value = $value;
}
public function doSomething()
{
echo $this->value;
})($val)
vs.
(new class ...
public function doSomething() use ($val)
{
echo $val;
})
It gets even uglier for passing by reference.
- Again, constructors can be used, and is less confusing than introducing
a new variable, but I'm open to persuasion if the idea is liked in general
...
This is fine when working with only a handful of values, but what about
needing access to a large number of values? What about making (especially
protected) method calls within the anon class?
Along the same vein, why did we even bother having "use" and $this for
closures, if you can after all just pass everything as arguments?
If there are realistic and elegant alternative solutions to the problems
presented, that's fair enough. Rejecting something because it's not as
simple to implement and you can hack around it in user code anyway...
that's a dangerous way to go about your business.
- Anonymous classes in PHP would support a constructor, so I don't see
the need for use to be utilized here, it would just clutter declarations
and the patch.This works, but it's more effort for the programmer and arguably just
moving the "clutter" from the declaration to the constructor.e.g.
(new class ...
protected $value;
public function __construct($value)
{
$this->value = $value;
}public function doSomething() { echo $this->value; })($val)
vs.
(new class ...
public function doSomething() use ($val)
{
echo $val;
})It gets even uglier for passing by reference.
- Again, constructors can be used, and is less confusing than introducing
a new variable, but I'm open to persuasion if the idea is liked in general
...This is fine when working with only a handful of values, but what about
needing access to a large number of values? What about making (especially
protected) method calls within the anon class?Along the same vein, why did we even bother having "use" and $this for
closures, if you can after all just pass everything as arguments?If there are realistic and elegant alternative solutions to the problems
presented, that's fair enough. Rejecting something because it's not as
simple to implement and you can hack around it in user code anyway...
that's a dangerous way to go about your business.
The first example doesn't make good sense:
(new class ...
protected $value;
public function __construct($value)
{
$this->value = $value;
}public function doSomething() { echo $this->value; })($val)
If $value is protected then how are you passing it in from outside as $val ?
If your anonymous class needs access to protected methods (which in turn
might want to read private members) then there's already an established
way of declaring that:
<?php
class Outer {
private $dice;
public function __construct($dice) {
$this->dice = $dice;
}
protected function protectedMethod() {
return $this->dice;
}
public function publicMethod() {
return new class extends Outer {
public function forwardToProtectedMethod() {
$this->protectedMethod();
}
}($this);
}
}
var_dump((new Outer($_SERVER))->publicMethod());
?>
This works now, as you expect it too ... not elegant enough ?? you don't
think use() everywhere might be a little bit much ??
Lets try to keep it as simple as possible, I think ...
Cheers
class A
{
}
class AProxifier
{
protected function protectedMethod() {...}
function getAProxy()
{
return new class extends A { /* How do you call
AProxifier->protectedMethod() here? */ };
}
}
This is possible with anonymous functions, that's a big feature of PHP5.4.
And for the same reasons might be expected here too?
I don't have the answer, just raising the point.
(new class ...
>> protected $value;
>> public function __construct($value)
>> {
>> $this->value = $value;
>> }
>>
>> public function doSomething()
>> {
>> echo $this->value;
>> })($val)
>>
>
Btw, I can't get used to ($val) beeing at the end of the declaration. I
feel it very confusing.
Nicolas
Am 26.09.2013 11:29 schrieb "Nicolas Grekas" nicolas.grekas+php@gmail.com:
Btw, I can't get used to ($val) beeing at the end of the declaration. I
feel it very confusing.
I feel the same. Couldn't this (constructor arguments) be moved?
$that = new class(/* constructor args /) / extends X implements Y */ {
... class body
};
> I think what Terence was talking about is more like this:
>
> class A
> {
> }
>
> class AProxifier
> {
> protected function protectedMethod() {...}
>
> function getAProxy()
> {
> return new class extends A { /* How do you call
> AProxifier->protectedMethod() here? */ };
> }
> }
>
> This is possible with anonymous functions, that's a big feature of PHP5.4.
> And for the same reasons might be expected here too?
> I don't have the answer, just raising the point.
>
>
> (new class ...
>>> protected $value;
>>> public function __construct($value)
>>> {
>>> $this->value = $value;
>>> }
>>>
>>> public function doSomething()
>>> {
>>> echo $this->value;
>>> })($val)
>>>
>>
>
> Btw, I can't get used to ($val) beeing at the end of the declaration. I
> feel it very confusing.
>
> Nicolas
>
If you need access to the methods in AProxifier then why does the
anonymous class extend A, you should extend AProxifier as you would with
any other class.
class A {
public function __construct(/* ctor args*/) {
/* ctor statements */
}
protected function protectedMethod() {
/* protected method */
}
public function getProxy() {
return new class extends A {
/* proxy stuff */
} (/* ctor args */);
}
}
For the following reasons the syntax should remain as it is:
It keeps the number of conflicts in the parser the same (%expect 3)
It is consistent with anonymous function calls - args after definition ...
It does not make sense to pass arguments to a constructor that might
not yet be declared
It is the simplest syntax to implement .. and so less margin for error,
easier to maintain in the future ...
Cheers
Joe
Am 26.09.2013 12:16 schrieb "Joe Watkins" krakjoe@php.net:
For the following reasons the syntax should remain as it is:
It is consistent with anonymous function calls - args after
definition ...
I think it is exceedingly rare for anynomous functions to be called at
their point of definition, while the constructor of your anonymous class
will alreays be called there.
It does not make sense to pass arguments to a constructor that
might not yet be declared
The constructor will be called after the full class definition has been
seen anyway; where the arguments are put syntactically doesn't change that,
does it?
My proposal ($that = new class(constructor args) places the constructor
args in exactly the same place they are when instantiating a nonanonymous
class.
best regards
Patrick
If you need access to the methods in AProxifier then why does the anonymous
class extend A, you should extend AProxifier as you would with any other
class.
Because A has the behavior I want to extend?
An other example:
class A {...}
class B {...}
class Factory
{
protected function protectedMethod() {...}
function getA()
{
return new class extends A {.. call Factory::protectedMethod()? ..};
}
function getB()
{
return new class extends B {.. call Factory::protectedMethod()? ..};
}
}
This is possible and welcomed with closures.
I see it as useful for anonymous classes than it is for anonymous functions.
What do others you think about it?
If you need access to the methods in AProxifier then why does the anonymous
class extend A, you should extend AProxifier as you would with any other
class.Because A has the behavior I want to extend?
An other example:
class A {...}
class B {...}class Factory
{
protected function protectedMethod() {...}function getA() { return new class extends A {.. call Factory::protectedMethod()? ..}; } function getB() { return new class extends B {.. call Factory::protectedMethod()? ..}; }
}
This is possible and welcomed with closures.
I see it as useful for anonymous classes than it is for anonymous functions.
What do others you think about it?
-1
Just because a closure is an anonymous function does not mean that an
anonymous class has closure capabilites.
--
Regards,
Mike
2013/9/27 Michael Wallner mike@php.net
On 27 September 2013 09:55, Nicolas Grekas nicolas.grekas+php@gmail.com
wrote:If you need access to the methods in AProxifier then why does the
anonymousclass extend A, you should extend AProxifier as you would with any other
class.Because A has the behavior I want to extend?
An other example:
class A {...}
class B {...}class Factory
{
protected function protectedMethod() {...}function getA() { return new class extends A {.. call Factory::protectedMethod()?
..};
} function getB() { return new class extends B {.. call Factory::protectedMethod()?
..};
}
}
This is possible and welcomed with closures.
I see it as useful for anonymous classes than it is for anonymous
functions.
What do others you think about it?-1
Just because a closure is an anonymous function does not mean that an
anonymous class has closure capabilites.
Just ... Isn't that something, we can simply keep out of this RFC and
create separate RFC(s) for it later? Like it was done with "$this in
Closures"?
--
Regards,
Mike--
Just ... Isn't that something, we can simply keep out of this RFC and
create separate RFC(s) for it later? Like it was done with "$this in
Closures"?
Do we want another 5.3/5.4 closures situation? Why not iron it all out to
begin with?
If there's a sound, logical reason not to implement the functionality in
question, that's fine. I don't understand why we keep reiterating "keeping
it simple" as if that is in itself an excuse to, in effect, rush it through
half-baked.
In the RFC, there are use cases citing languages like Java to support this
- a language in which anonymous classes and the methods in which they're
defined, share scope. Can we then say, let's do it because it's useful in
other languages, but let's not offer the functionality that those languages
do? Also, my proposed use case being practical in the real world hangs on
resolving the scope issue, as I struggle to look past the difficulties I'd
have trying to use this in my code when it's unable to interact with the
object instance in which it is being used.
That's all I'll say on that now; it's becoming circular.
If you want to update my use case in the RFC, here's an expanded example of
what I imagine. I've lifted code from the documentation for Sentry* and
below it, written an alternative anonymous class API example.
- I have no affiliation with Sentry / other membership packages are
available.
try
{
// Find the user using the user id
$user = Sentry::findUserById(1);
// Log the user in
Sentry::login($user, false);
}
catch (Cartalyst\Sentry\Users\LoginRequiredException $e)
{
echo 'Login field is required.';
}
catch (Cartalyst\Sentry\Users\UserNotActivatedException $e)
{
echo 'User not activated.';
}
catch (Cartalyst\Sentry\Users\UserNotFoundException $e)
{
echo 'User not found.';
}
// Following is only needed if throttle is enabled
catch (Cartalyst\Sentry\Throttling\UserSuspendedException $e)
{
$time = $throttle->getSuspensionTime();
echo "User is suspended for [$time] minutes.";
}
catch (Cartalyst\Sentry\Throttling\UserBannedException $e)
{
echo 'User is banned.';
}
becomes:
$user = Sentry::findUserById(
1,
(new class implements Cartalyst\Sentry\LoginHandlerInterface
{
public function onLoginRequired()
{
echo 'Login field is required.';
}
public function onUserNotActivated()
{
echo 'User not activated.';
}
public function onUserNotFound()
{
echo 'User not found.';
}
// Following is only needed if throttle is enabled
public function onUserSuspended()
{
$time = $throttle->getSuspensionTime();
echo "User is suspended for [$time] minutes.";
}
public function onUserBanned()
{
echo 'User is banned.';
}
public function onSuccess()
{
// Log the user in
Sentry::login($user, false);
}
})
);
Just ... Isn't that something, we can simply keep out of this RFC and
create separate RFC(s) for it later? Like it was done with "$this in
Closures"?Do we want another 5.3/5.4 closures situation? Why not iron it all out to
begin with?If there's a sound, logical reason not to implement the functionality in
question, that's fine. I don't understand why we keep reiterating "keeping
it simple" as if that is in itself an excuse to, in effect, rush it through
half-baked.In the RFC, there are use cases citing languages like Java to support this
- a language in which anonymous classes and the methods in which they're
defined, share scope. Can we then say, let's do it because it's useful in
other languages, but let's not offer the functionality that those languages
do? Also, my proposed use case being practical in the real world hangs on
resolving the scope issue, as I struggle to look past the difficulties I'd
have trying to use this in my code when it's unable to interact with the
object instance in which it is being used.That's all I'll say on that now; it's becoming circular.
If you want to update my use case in the RFC, here's an expanded example of
what I imagine. I've lifted code from the documentation for Sentry* and
below it, written an alternative anonymous class API example.
- I have no affiliation with Sentry / other membership packages are
available.try
{
// Find the user using the user id
$user = Sentry::findUserById(1);
// Log the user in
Sentry::login($user, false);
}
catch (Cartalyst\Sentry\Users\LoginRequiredException $e)
{
echo 'Login field is required.';
}
catch (Cartalyst\Sentry\Users\UserNotActivatedException $e)
{
echo 'User not activated.';
}
catch (Cartalyst\Sentry\Users\UserNotFoundException $e)
{
echo 'User not found.';
}
// Following is only needed if throttle is enabled
catch (Cartalyst\Sentry\Throttling\UserSuspendedException $e)
{
$time = $throttle->getSuspensionTime();
echo "User is suspended for [$time] minutes.";
}
catch (Cartalyst\Sentry\Throttling\UserBannedException $e)
{
echo 'User is banned.';
}becomes:
$user = Sentry::findUserById(
1,
(new class implements Cartalyst\Sentry\LoginHandlerInterface
{
public function onLoginRequired()
{
echo 'Login field is required.';
}
public function onUserNotActivated()
{
echo 'User not activated.';
}
public function onUserNotFound()
{
echo 'User not found.';
}
// Following is only needed if throttle is enabled
public function onUserSuspended()
{
$time = $throttle->getSuspensionTime();
echo "User is suspended for [$time] minutes.";
}
public function onUserBanned()
{
echo 'User is banned.';
}
public function onSuccess()
{
// Log the user in
Sentry::login($user, false);
}
})
);
Because in your rush to get the ironing done, you are burning clothes,
putting big holes in them, and are going to be left with no clothes
without big holes in them ...
What we are introducing here is anonymous classes, not nested classes:
class Outer {
class Inner {
class Again {
class Inner {
}
}
}
}
This requires a way to resolve complex scope issues, these are formally
nested classes, as yet unsupported, formally nested classes might also
look like:
class Outer {
class Inner {
protected class Again {
private class Inner {
}
}
}
}
I appreciate that the only way to do this right now is with anonymous
classes, but if you are doing it with anonymous classes then you,
clearly, do not care about scope.
The solution to the resolution of nested class scope issues does not
belong as part of the RFC introducing anonymous classes but the RFC
introducing nested classes, which is as yet unwritten, but totally doable.
+1000 on keeping this for another RFC, because it's part of another
problem ...
Cheers
Joe
Just ... Isn't that something, we can simply keep out of this RFC and
create separate RFC(s) for it later? Like it was done with "$this in
Closures"?Do we want another 5.3/5.4 closures situation? Why not iron it all out to
begin with?If there's a sound, logical reason not to implement the functionality in
question, that's fine. I don't understand why we keep reiterating "keeping
it simple" as if that is in itself an excuse to, in effect, rush it
through
half-baked.In the RFC, there are use cases citing languages like Java to support this
- a language in which anonymous classes and the methods in which they're
defined, share scope. Can we then say, let's do it because it's useful in
other languages, but let's not offer the functionality that those
languages
do? Also, my proposed use case being practical in the real world hangs on
resolving the scope issue, as I struggle to look past the difficulties I'd
have trying to use this in my code when it's unable to interact with the
object instance in which it is being used.That's all I'll say on that now; it's becoming circular.
If you want to update my use case in the RFC, here's an expanded example
of
what I imagine. I've lifted code from the documentation for Sentry* and
below it, written an alternative anonymous class API example.
- I have no affiliation with Sentry / other membership packages are
available.try
{
// Find the user using the user id
$user = Sentry::findUserById(1);
// Log the user in
Sentry::login($user, false);
}
catch (Cartalyst\Sentry\Users**LoginRequiredException $e)
{
echo 'Login field is required.';
}
catch (Cartalyst\Sentry\Users**UserNotActivatedException $e)
{
echo 'User not activated.';
}
catch (Cartalyst\Sentry\Users*UserNotFoundException $e)
{
echo 'User not found.';
}
// Following is only needed if throttle is enabled
catch (Cartalyst\Sentry\Throttling*UserSuspendedException $e)
{
$time = $throttle->getSuspensionTime();
echo "User is suspended for [$time] minutes.";
}
catch (Cartalyst\Sentry\Throttling**UserBannedException $e)
{
echo 'User is banned.';
}becomes:
$user = Sentry::findUserById(
1,
(new class implements Cartalyst\Sentry*LoginHandlerInterface
{
public function onLoginRequired()
{
echo 'Login field is required.';
}
public function onUserNotActivated()
{
echo 'User not activated.';
}
public function onUserNotFound()
{
echo 'User not found.';
}
// Following is only needed if throttle is enabled
public function onUserSuspended()
{
$time = $throttle->getSuspensionTime()*;
echo "User is suspended for [$time] minutes.";
}
public function onUserBanned()
{
echo 'User is banned.';
}
public function onSuccess()
{
// Log the user in
Sentry::login($user, false);
}
})
);Because in your rush to get the ironing done, you are burning clothes,
putting big holes in them, and are going to be left with no clothes without
big holes in them ...What we are introducing here is anonymous classes, not nested classes:
class Outer {
class Inner {
class Again {
class Inner {} } }
}
This requires a way to resolve complex scope issues, these are formally
nested classes, as yet unsupported, formally nested classes might also look
like:class Outer {
class Inner {
protected class Again {
private class Inner {} } }
}
I appreciate that the only way to do this right now is with anonymous
classes, but if you are doing it with anonymous classes then you, clearly,
do not care about scope.The solution to the resolution of nested class scope issues does not
belong as part of the RFC introducing anonymous classes but the RFC
introducing nested classes, which is as yet unwritten, but totally doable.+1000 on keeping this for another RFC, because it's part of another
problem ...Cheers
Joe
I think you've become confused with my intentions here. My example is not
of the internal workings of an API and I'm certainly not talking about
nested classes. My example is of a third party using an API from the
outside. Currently, the way the package given in my example communicates is
by using exceptions to signal what happened. What I'm demonstrating is that
a more expressive way to do this would be to instead pass a callback
anonymous class to handle those outcomes, rather than having a series of
catch blocks.
I only think it would be good to actually discuss (i.e. discuss i.e. not
dismiss based on personal preference or deflect using obscure metaphors)
the scope implications of this feature which inherently poses questions
about scope. I don't understand the insistence on addressing this in a
separate RFC when it is pertinent to this very feature.
Just ... Isn't that something, we can simply keep out of this RFC and
create separate RFC(s) for it later? Like it was done with "$this in
Closures"?Do we want another 5.3/5.4 closures situation? Why not iron it all out to
begin with?If there's a sound, logical reason not to implement the functionality in
question, that's fine. I don't understand why we keep reiterating "keeping
it simple" as if that is in itself an excuse to, in effect, rush it
through
half-baked.In the RFC, there are use cases citing languages like Java to support this
- a language in which anonymous classes and the methods in which they're
defined, share scope. Can we then say, let's do it because it's useful in
other languages, but let's not offer the functionality that those
languages
do? Also, my proposed use case being practical in the real world hangs on
resolving the scope issue, as I struggle to look past the difficulties I'd
have trying to use this in my code when it's unable to interact with the
object instance in which it is being used.That's all I'll say on that now; it's becoming circular.
If you want to update my use case in the RFC, here's an expanded example
of
what I imagine. I've lifted code from the documentation for Sentry* and
below it, written an alternative anonymous class API example.
- I have no affiliation with Sentry / other membership packages are
available.try
{
// Find the user using the user id
$user = Sentry::findUserById(1);
// Log the user in
Sentry::login($user, false);
}
catch (Cartalyst\Sentry\Users**LoginRequiredException $e)
{
echo 'Login field is required.';
}
catch (Cartalyst\Sentry\Users**UserNotActivatedException $e)
{
echo 'User not activated.';
}
catch (Cartalyst\Sentry\Users*UserNotFoundException $e)
{
echo 'User not found.';
}
// Following is only needed if throttle is enabled
catch (Cartalyst\Sentry\Throttling*UserSuspendedException $e)
{
$time = $throttle->getSuspensionTime();
echo "User is suspended for [$time] minutes.";
}
catch (Cartalyst\Sentry\Throttling**UserBannedException $e)
{
echo 'User is banned.';
}becomes:
$user = Sentry::findUserById(
1,
(new class implements Cartalyst\Sentry*LoginHandlerInterface
{
public function onLoginRequired()
{
echo 'Login field is required.';
}
public function onUserNotActivated()
{
echo 'User not activated.';
}
public function onUserNotFound()
{
echo 'User not found.';
}
// Following is only needed if throttle is enabled
public function onUserSuspended()
{
$time = $throttle->getSuspensionTime()*;
echo "User is suspended for [$time] minutes.";
}
public function onUserBanned()
{
echo 'User is banned.';
}
public function onSuccess()
{
// Log the user in
Sentry::login($user, false);
}
})
);Because in your rush to get the ironing done, you are burning clothes,
putting big holes in them, and are going to be left with no clothes without
big holes in them ...What we are introducing here is anonymous classes, not nested classes:
class Outer {
class Inner {
class Again {
class Inner {} } }
}
This requires a way to resolve complex scope issues, these are formally
nested classes, as yet unsupported, formally nested classes might also look
like:class Outer {
class Inner {
protected class Again {
private class Inner {} } }
}
I appreciate that the only way to do this right now is with anonymous
classes, but if you are doing it with anonymous classes then you, clearly,
do not care about scope.The solution to the resolution of nested class scope issues does not
belong as part of the RFC introducing anonymous classes but the RFC
introducing nested classes, which is as yet unwritten, but totally doable.+1000 on keeping this for another RFC, because it's part of another
problem ...Cheers
JoeI think you've become confused with my intentions here. My example is not
of the internal workings of an API and I'm certainly not talking about
nested classes. My example is of a third party using an API from the
outside. Currently, the way the package given in my example communicates is
by using exceptions to signal what happened. What I'm demonstrating is that
a more expressive way to do this would be to instead pass a callback
anonymous class to handle those outcomes, rather than having a series of
catch blocks.I only think it would be good to actually discuss (i.e. discuss i.e. not
dismiss based on personal preference or deflect using obscure metaphors)
the scope implications of this feature which inherently poses questions
about scope. I don't understand the insistence on addressing this in a
separate RFC when it is pertinent to this very feature.
Wires crossed I think ... I wasn't commenting on the updated use case, I
didn't update it simply because there is surely enough information
regarding use cases included in the RFC now, I think everyone gets the
use case thing.
With regard to the scope issues; what anonymous classes allow, in
effect, is for you to nest classes, it just so happens they do not have
a declared name. I agree that issues of scope are relevant, but the
resolution to the problem doesn't belong here, it belongs in the formal
support of nesting classes, and as far as possible it will be addressed
there, grafting a solution to the scope issues onto anonymous classes
could only make it harder to formally nest classes.
If no decent solutions to formally nesting classes can be found or
accepted then the problem of scope in anonymous classes might need a
solution in its own right ... for now the solution belongs with nesting,
which is what anonymous classes actually are (when used inside another
class).
Cheers
Joe
Morning All,
https://wiki.php.net/rfc/anonymous_classes I'd like to hear thoughts regarding the addition of anonymous
classes, patch included.
Cheers
Joe
Thanks chaps ...
I am having a hard time picturing a real-world use-case for this.
-Rasmus
I think since you wrote that quite a few decent use cases have been
suggested, testing, MVC (that wasn't on internals), throw away/private
implementation of interfaces or abstracts.
It has such a wide range of uses, I didn't think it necessary to point
them out, as others have mentioned it's an established OO pattern to use
objects of an anonymous class.
I'd rather go for a
new BaseType
syntax, though:$subject->attach(new SplObserver() {
function update(SplSubject $s) {
printf("Got update from: %s\n" $subject);
}
);
Using class_name_reference in place of T_CLASS
causes a conflict with
existing syntax, which is the reason T_CLASS
is accepted, additionally,
using class is nicer shorthand for new stdClass {}.
With that in mind, I haven't tried moving the arguments, this:
(new class {definition} (arguments))->method()
seems more natural/sensible than:
(new class(arguments) {definition})->method()
new class() just feels a bit wrong ...
Frankly, constructors are not part of any interface. Besides a
constructor
is totally useless in an anonymous class as it will never be called
after
the object is created.
The examples in the constructor were not meant as use cases but to show
the syntax of use.
If you are using an anonymous class to implement an interface then a
constructor may not be required, however, removing the ability to
declare a constructor is restrictive an unnecessary.
Cheers
Joe
Hi Joe,
what about serialization for those classes?
cu,
Lars
Am 23.09.2013 um 08:39 schrieb Joe Watkins krakjoe@php.net:
Morning All,
https://wiki.php.net/rfc/anonymous_classes
I'd like to hear thoughts regarding the addition of anonymous classes, patch included.
Cheers
Joe
Hi Joe,
what about serialization for those classes?
cu,
LarsAm 23.09.2013 um 08:39 schrieb Joe Watkins krakjoe@php.net:
Morning All,
https://wiki.php.net/rfc/anonymous_classes I'd like to hear thoughts regarding the addition of anonymous classes, patch included.
Cheers
Joe--
Same as any other object; what you are creating is normal classes
without a (declared) name, nothing about the objects functionality has
differs from an object of a named class.
Cheers
Am 23.09.2013 16:06 schrieb "Joe Watkins" krakjoe@php.net:
what about serialization for those classes?
Same as any other object; what you are creating is normal classes without
a (declared) name, nothing about the objects functionality has differs from
an object of a named class.
What about UNserialize then? Will you extend the serialized format to
include the full definition of the anonymous class, so that it can be
reinstated at unserialization time? If not, what will be the class (and
baseclass and interfaces) of the unserialized formerly-anonymous objects?
best regards
Patrick
What about UNserialize then?
I don't see any way to handle this sensibly, but I also don't regard this as
a
problem, because that's not what these anonymous classes are for. If you
want
something that can be unserialised into a thing with methods then logically
you
know what it is ahead of time, because you know what functionality you want
it
to have, so you would have a named class for it. If you don't want it to
have
methods then it's just a value object and stdClass will suffice (you
wouldn't
have created the anonymous class in the first place).
All? the use cases mentioned are centred around interfaces and interfaces
don't
include values (i.e. properties), which is all that serialisation stores
apart
from the class name, which by definition doesn't apply to anonymous classes.
The opposite of this problem, unserialising anonymous objects into instances
of
defined classes, would be very useful in many places (especially JSON) but I
guess that's another prickly issue for another thread.
To summarize how I think this should be handled: Serialisation results in a
stdClass, unserialisation cannot be done because if you want it you're
already
Doing It WrongT.
To summarize how I think this should be handled: Serialisation results in a
stdClass, unserialisation cannot be done because if you want it you're
already
Doing It WrongT.
To me, serialising "successfully" would indicate that PHP could
unserialise the object as it was. Since it can't, I'd prefer to just
error out at the serialize()
stage.
As for the feature itself, I'm not really sold right now. The use
cases I've seen for this previously in other languages have been
situations where either a simple anonymous function or closure would
suffice, or alternatively situations where you have a big anonymous
class with lots of methods, and I think for the latter case I'd rather
promote separating those sorts of implementations into standalone
classes for readability reasons.
Adam, who isn't even pretending that he's looked at the patch yet.
Hi,
Hi Joe,
what about serialization for those classes?
cu,
LarsSame as any other object; what you are creating is normal classes without
a (declared) name, nothing about the objects functionality has differs from
an object of a named class.
I think that the question was: How would you figure out method
implementation for unserialized object of anonymous class? Consider this
example...
$o = new class() {
private $a = 1;
public function test() { echo $this->a; }
};
$o->test();
$str = serialize($o);
$o2 = unserialize($str);
$o2->test();
How would this work?
Jakub
2013/9/23 Joe Watkins krakjoe@php.net
Hi Joe,
what about serialization for those classes?
cu,
LarsAm 23.09.2013 um 08:39 schrieb Joe Watkins krakjoe@php.net:
Morning All,
https://wiki.php.net/rfc/**anonymous_classes<https://wiki.php.net/rfc/anonymous_classes> I'd like to hear thoughts regarding the addition of anonymous
classes, patch included.
Cheers
Joe--
Same as any other object; what you are creating is normal classes without
a (declared) name, nothing about the objects functionality has differs from
an object of a named class.
When you serialize an object the serialized form contains the class name.
So as long as the instance doesn't have a own class name it isn't possible
to serialize it properly and even further to unserialize it, because the
whole definition is gone. To sum it up: They aren't serializable.
Imo it isn't such a flaw, that anonymous instances aren't serializable,
because anonymous functions/closures aren't neither.
Regards,
Sebastian.
Cheers
--
Morning All,
https://wiki.php.net/rfc/anonymous_classes I'd like to hear thoughts regarding the addition of anonymous
classes, patch included.
Cheers
Joe
Serialization:
As I have said, serialization does work, and unserialization does
work ...
Classes do have unique names, so as long as the entry is present upon
unserialize you will get the object you expect ... if the entry is not
present unserialization will fail silently.
The same kind of thing can happen where you have declared a class
based on some predicate, whose value has changed upon unserialize and so
the entry is not present ...
I'm not sure it is necessary to force any particular behaviour for
serialization, it depends entirely on the application whether or not the
entry is present upon serialization, it should be left down to the
programmer.
Cheers
Joe
Everyone,
As a lurker i rarely have anthing to say, but this time i'd like to make an
exception: I see some usability for this type of usage, but would like to
disagree on the extra class...
My usage would be more in line with JSON way of passing around objects...
But i'd hate to see yet another new class type and kind of feel the
StdClass would've been more logical...
The reasons for this imho is that the StdClass is the one-for-all object
without anything that's already there... (it's not like anonymous functions
are something different than regular functions?)
As for actual need: personally i can easily live without, but then again:
we the influx of JSON-like notation / ubiquity this might make a logical
follow up.. ?
Met vriendelijke groet,
Robin Speekenbrink
Kingsquare BV
2013/9/23 Joe Watkins krakjoe@php.net
Morning All,
https://wiki.php.net/rfc/**anonymous_classes<https://wiki.php.net/rfc/anonymous_classes> I'd like to hear thoughts regarding the addition of anonymous
classes, patch included.
Cheers
JoeSerialization:
As I have said, serialization does work, and unserialization does work
...Classes do have unique names, so as long as the entry is present upon
unserialize you will get the object you expect ... if the entry is not
present unserialization will fail silently.The same kind of thing can happen where you have declared a class based
on some predicate, whose value has changed upon unserialize and so the
entry is not present ...I'm not sure it is necessary to force any particular behaviour for
serialization, it depends entirely on the application whether or not the
entry is present upon serialization, it should be left down to the
programmer.Cheers
Joe
2013/9/23 Kingsquare.nl - Robin Speekenbrink robin@kingsquare.nl
Everyone,
As a lurker i rarely have anthing to say, but this time i'd like to make an
exception: I see some usability for this type of usage, but would like to
disagree on the extra class...
My usage would be more in line with JSON way of passing around objects...
But i'd hate to see yet another new class type and kind of feel the
StdClass would've been more logical...
To me it sounds like you mix something up and describe a different use case
(which is already easily possible)
$stdClass = (object) [
'foo' => 'bar'
];
The RFC is about anonymous objects with behaviour (-> methods), whereas
stdClass-objects doesn't have any methods.
The reasons for this imho is that the StdClass is the one-for-all object
without anything that's already there... (it's not like anonymous functions
are something different than regular functions?)As for actual need: personally i can easily live without, but then again:
we the influx of JSON-like notation / ubiquity this might make a logical
follow up.. ?Met vriendelijke groet,
Robin Speekenbrink
Kingsquare BV2013/9/23 Joe Watkins krakjoe@php.net
Morning All,
https://wiki.php.net/rfc/**anonymous_classes<
https://wiki.php.net/rfc/anonymous_classes>
I'd like to hear thoughts regarding the addition of anonymous
classes, patch included.
Cheers
JoeSerialization:
As I have said, serialization does work, and unserialization does work
...Classes do have unique names, so as long as the entry is present upon
unserialize you will get the object you expect ... if the entry is not
present unserialization will fail silently.The same kind of thing can happen where you have declared a class based
on some predicate, whose value has changed upon unserialize and so the
entry is not present ...I'm not sure it is necessary to force any particular behaviour for
serialization, it depends entirely on the application whether or not the
entry is present upon serialization, it should be left down to the
programmer.Cheers
Joe--
Hi Joe,
Am 23.09.2013 um 19:22 schrieb Joe Watkins krakjoe@php.net:
[...]
As I have said, serialization does work, and unserialization does work ...
Classes do have unique names, so as long as the entry is present upon unserialize you will get the object you expect ... if the entry is not present unserialization will fail silently.
The same kind of thing can happen where you have declared a class based on some predicate, whose value has changed upon unserialize and so the entry is not present ...
I'm not sure it is necessary to force any particular behaviour for serialization, it depends entirely on the application whether or not the entry is present upon serialization, it should be left down to the programmer.
it would make sense to forbid serializing anonymous classes like we forbid serializing closures. What do you think?
cu,
Lars
Hi,
Serialization:
As I have said, serialization does work, and unserialization does work
...Classes do have unique names, so as long as the entry is present upon
unserialize you will get the object you expect ... if the entry is not
present unserialization will fail silently.The same kind of thing can happen where you have declared a class based
on some predicate, whose value has changed upon unserialize and so the
entry is not present ...I'm not sure it is necessary to force any particular behaviour for
serialization, it depends entirely on the application whether or not the
entry is present upon serialization, it should be left down to the
programmer.
sorry if I missed something when I read your patch but the name of the
class is defined as Class$$%lu where %lu is substituted by the current
compiler global variable anon_class_id that is incremented before. This
could lead to the unexpected results when the script that unserialize
objects define anonymous classes in different order than serializing
script. Then you can get completely different definition. In most cases you
would get when you try to use some method that are not defined but you
could also have something like this:
serialize script
<?php
$a = new class() { public $a = 100; public function foo() { echo $a + 1; }
} // class name: Class$$1
$b = new class() { public $a = 0; public function foo() { echo $a - 1; } }
// class name: Class$$2
$str = serialize(array($a, $b)); // str:
a:2:{i:0;O:8:"Class$$1":1:{s:1:"a";i:100;}i:1;O:8:"Class$$2":1:{s:1:"a";i:0;}}
save_str_to_db($str);
$a->foo(); // 101
$b->foo(); // -1
unserialize script
<?php
new class() { public $a; public function foo() { echo $a - 1; } } // class
name: Class$$1
new class() { public $a; public function foo() { echo $a + 1; } } // class
name: Class$$2
$str = load_str_from_db();
list($a,$b) = unserialize($str);
$a->foo(); // 99
$b->foo(); // 1
I know that this just a non-sense example but there could be some more
complex situations that this could happened. You will get different result
just because the classes are defined in different order...
As I said I could miss something but if this is the case I think that the
serialization issue should be addressed in the patch.
Jakub
2013/9/23 Joe Watkins krakjoe@php.net
Morning All,
https://wiki.php.net/rfc/**anonymous_classes<https://wiki.php.net/rfc/anonymous_classes> I'd like to hear thoughts regarding the addition of anonymous
classes, patch included.
Cheers
JoeSerialization:
As I have said, serialization does work, and unserialization does work
...
Actually if you cant unserialize a "serialized object", it isn't a
serialized object, but only a string describing the object it was created
from.
Classes do have unique names, so as long as the entry is present upon
unserialize you will get the object you expect ... if the entry is not
present unserialization will fail silently.
Which name do you give them? The name of the originating interface/class?
if ($debug) {
$listener = new class extends ListenerInterface () {
public function onFoo() { debug(); };
};
} else {
$listener = new class extends ListenerInterface () {
public function onFoo() { normal(); };
};
}
$someBar->addListener($listener);
$x = serialize($listener);
The same kind of thing can happen where you have declared a class based
on some predicate, whose value has changed upon unserialize and so the
entry is not present ...
I'm not sure it is necessary to force any particular behaviour for
serialization, it depends entirely on the application whether or not the
entry is present upon serialization, it should be left down to the
programmer.
Cheers
Joe--
What about allowing a "use" statement on these methods?
$someFoo = "bar";
$object = new class{
function method() use ($someFoo) { return $someFoo;}
}
$object->method(); // "bar";
On 24 September 2013 14:51, Nicolas Grekas nicolas.grekas+php@gmail.comwrote:
What about allowing a "use" statement on these methods?
$someFoo = "bar";
$object = new class{
function method() use ($someFoo) { return $someFoo;}
}$object->method(); // "bar";
I think the idea of anonymous classes is very useful.
a use case that I recently encountered, is to override a specific method in
a class.
So instead of creating a new class that extends the original class, you can
just use an anonymous class and override the methods that you want.
E.G.
You can to the following:
use Symfony\Component\Process\Process;
$process = new class extends Process {
public function start() {
/* ... */
}
};
instead of the following:
namespace My\Namespace\Process;
use Symfony\Component\Process\Process as Base;
class Process extends Base {
public function start() {
/* ... */
}
}
$process = new \My\Namespace\Process\Process;
hi!
Morning All,
https://wiki.php.net/rfc/anonymous_classes
I'd like to hear thoughts regarding the addition of anonymous classes,
patch included.
Thanks for your proposal and work.
If you did not yet update your RFC I would suggest to do so, it is about
the right time.
Adding already answered questions, more use cases (read a couple of good
ones in this thread). It will help to end in circular discussions or
arguing.
Cheers,
Pierre
hi!
Morning All,
https://wiki.php.net/rfc/anonymous_classes
I'd like to hear thoughts regarding the addition of anonymous classes,
patch included.Thanks for your proposal and work.
If you did not yet update your RFC I would suggest to do so, it is about
the right time.Adding already answered questions, more use cases (read a couple of good
ones in this thread). It will help to end in circular discussions or
arguing.Cheers,
Pierre
Thanks ...
I have made many changes to the RFC and patch since the beginning of
this discussion ...
It might be useful if you could all now go back to the RFC for another
read, point out anything I've left unclear at this point.
Cheers
Joe
2013/9/26 Joe Watkins krakjoe@php.net
hi!
Morning All,
https://wiki.php.net/rfc/**anonymous_classeshttps://wiki.php.net/rfc/anonymous_classes
I'd like to hear thoughts regarding the addition of anonymous classes,
patch included.Thanks for your proposal and work.
If you did not yet update your RFC I would suggest to do so, it is about
the right time.Adding already answered questions, more use cases (read a couple of good
ones in this thread). It will help to end in circular discussions or
arguing.Cheers,
PierreThanks ...
I have made many changes to the RFC and patch since the beginning of this
discussion ...It might be useful if you could all now go back to the RFC for another
read, point out anything I've left unclear at this point.
Thank you for the updates.
There is a possible mistake in the "Inheritance" section. The $this->data
array is passed by value to the constructor of the anonymous class. Once
there is any change to the initial array, the two classes will contain
different data.
Which leads us to the point that this pattern is not enough to do what you
wanted to without changing the original constructor. This is usually out of
the question, as one such change will also change the outer class' behavior.
We don't have to reinvent the wheel here. The solution is some kind of
"use" clause that works similarly to the anonymous functions.
Cheers,
Lazare INEPOLOGLOU
Ingénieur Logiciel
2013/9/26 Joe Watkins krakjoe@php.net
hi!
Morning All,
https://wiki.php.net/rfc/**anonymous_classeshttps://wiki.php.net/rfc/anonymous_classes
I'd like to hear thoughts regarding the addition of anonymous classes,
patch included.Thanks for your proposal and work.
If you did not yet update your RFC I would suggest to do so, it is about
the right time.Adding already answered questions, more use cases (read a couple of good
ones in this thread). It will help to end in circular discussions or
arguing.Cheers,
PierreThanks ...
I have made many changes to the RFC and patch since the beginning of this
discussion ...It might be useful if you could all now go back to the RFC for another
read, point out anything I've left unclear at this point.Thank you for the updates.
There is a possible mistake in the "Inheritance" section. The $this->data
array is passed by value to the constructor of the anonymous class. Once
there is any change to the initial array, the two classes will contain
different data.Which leads us to the point that this pattern is not enough to do what you
wanted to without changing the original constructor. This is usually out of
the question, as one such change will also change the outer class' behavior.We don't have to reinvent the wheel here. The solution is some kind of
"use" clause that works similarly to the anonymous functions.Cheers,
Lazare INEPOLOGLOU
Ingénieur Logiciel
We don't have to re-invent the wheel, pass by reference if that's what
you want to do, the example didn't make any changes to data, tests
included with the patch do, and it, of course, works ...
Cheers
Thanks ...
I have made many changes to the RFC and patch since the beginning of this
discussion ...It might be useful if you could all now go back to the RFC for another
read, point out anything I've left unclear at this point.
I saw your changes :) I would add more use cases if possible, the more the
better.
My feeling is that some does not see yet a good use case. It is a known
pattern is sometimes not a good enough argument.
Cheers,
Thanks ...
I have made many changes to the RFC and patch since the beginning of this
discussion ...It might be useful if you could all now go back to the RFC for another
read, point out anything I've left unclear at this point.I saw your changes :) I would add more use cases if possible, the more the
better.My feeling is that some does not see yet a good use case. It is a known
pattern is sometimes not a good enough argument.Cheers,
Ok, I included just about all the information on use cases that is
obvious or has been discussed, so I think we got use cases covered now,
right ??
See a good one yet ??
Cheers
Joe
Ok, I included just about all the information on use cases that is obvious
or has been discussed, so I think we got use cases covered now, right ??See a good one yet ??
Cheers
Joe
Wondering about scoping. Yes, anonymous classes can have their own
constructor, but if we're adding syntactic sugar why not make it
possible to use from the scope they're created in?
See this example adapted from a Stack Overflow question about how it
works in Java [1]:
(not sure how you the "use" syntax should look like)
public function doStuff($userId) {
$this->doOtherStuff($userId, new class implements SomeInterface {
public function onSuccess() {
echo $userId;
}
});
}
vs
public function doStuff($userId) {
$this->doOtherStuff($userId, new class implements SomeInterface {
private $userId;
public function __construct($userId) {
$this->userId = $userId;
}
public function onSuccess() {
echo $this->userId;
}
});
}
[1] http://stackoverflow.com/questions/3251018/java-anonymous-inner-class-using-a-local-variable
Cheers,
Alexander
hi Joe!
Ok, I included just about all the information on use cases that is obvious
or has been discussed, so I think we got use cases covered now, right ??
Thanks for the updates!
See a good one yet ??
I think it should be enough, and you have my voice now :)
As of the other requests here, like nested classes (which I really do
not like from a design point of view), I do not think they fit in this
RFC.
Cheers,
Pierre
@pierrejoye | http://www.libgd.org