A couple of things that would really help me in PHP are generics and the
ability to set default values of properties to instances of objects or
calls to static methods or functions (expressions in general).
I don't know if either of these have experimental implementations already
as I couldn't find any, but if it would add some interest I may be willing
to tackle the source to help push it forward.
Could you please advise me on any fatal barriers that might prevent this
being worth while for me. Thank you.
Dominic
Hey Dominic
A couple of things that would really help me in PHP are generics and the
ability to set default values of properties to instances of objects or
calls to static methods or functions (expressions in general).I don't know if either of these have experimental implementations already
as I couldn't find any, but if it would add some interest I may be willing
to tackle the source to help push it forward.Could you please advise me on any fatal barriers that might prevent this
being worth while for me. Thank you.Dominic
So far I only wrote up the RFC and kicked off a discussion here on the
mailing list about it. As I wrote several times already, I'd appreciate
someone tackling the implementation side to get a patch working!
Cheers,
Ben Scholzen 'DASPRiD'
Community Review Team Member | mail@dasprids.de
Zend Framework | http://www.dasprids.de
Hi,
Would be good to split complete different subjects to different threads
anyways:
the
ability to set default values of properties to instances of objects or
calls to static methods or functions (expressions in general).
This causes questions on the order of execution and leads to waste of
CPU time in case the constructor overrides the default value while not
bringing much benefit over initialization in the constructor. It also is
complicated regarding exceptions being thrown.
Take the following code:
<?php
foo();
class A {
protected $p1 = new Something();
private $p2 = new SomethingElse($this->p1, $this->p3);
private $p3 = new Something();
private static $s1 = new StaticSomething();
public function __construct() {}
}
bar();
class B extends A {
private $p4 = new Something();
public function __construct() {
parent::__construct();
$this->p1 = new Whatever();
}
}
baz();
try {
$b = new B();
} catch (Exception $e) {
}
?>
Some Questions:
* Where, relative to foo(), bar() and baz() will StaticSomething's
constructor be called? How do you capture exceptions from there?
* When will $p2 be initialized, which properties can it access?
(Only the ones initialized before? None?)
* In B's constructor we're overwriting $p1, so $p2 will be
initialized with the wrong value.
I'm sure there are more questions ... doing this i the constructor makes
things clear and explicit with about the same amount of code to write.
johannes
Hi,
I see what you mean with static properties, that would be more difficult.
I can answer on non-static however.
- When will $p2 be initialized, which properties can it access?
- On class instantiation. It won't have access to $this, because the
object won't have been created yet. It will have access to the same
entities as a static method.
- In B's constructor we're overwriting $p1, so $p2 will be initialized with
the wrong value.
- It won't have access to $this. In effect they are pre-constructor
assignments, just like any other property.
Concerning reassignment on constructor leading to wasted code, I can only
place faith in the effectiveness of the user to override those properties
to NULL.
Anyway sorry about the mixed post. I've mainly been working on
implementing generics, so I have a separate thread somewhere for that.
Dominic
Hi,
Would be good to split complete different subjects to different threads
anyways:the
ability to set default values of properties to instances of objects or
calls to static methods or functions (expressions in general).This causes questions on the order of execution and leads to waste of
CPU time in case the constructor overrides the default value while not
bringing much benefit over initialization in the constructor. It also is
complicated regarding exceptions being thrown.Take the following code:
<?php
foo();
class A {
protected $p1 = new Something();
private $p2 = new SomethingElse($this->p1, $this->p3);
private $p3 = new Something();
private static $s1 = new StaticSomething();public function __construct() {}
}bar();
class B extends A {
private $p4 = new Something();public function __construct() { parent::__construct(); $this->p1 = new Whatever(); }
}
baz();
try {
$b = new B();
} catch (Exception $e) {
}
?>Some Questions:
* Where, relative to foo(), bar() and baz() will StaticSomething's constructor be called? How do you capture exceptions from there? * When will $p2 be initialized, which properties can it access? (Only the ones initialized before? None?) * In B's constructor we're overwriting $p1, so $p2 will be initialized with the wrong value.
I'm sure there are more questions ... doing this i the constructor makes
things clear and explicit with about the same amount of code to write.johannes
Hi!
ability to set default values of properties to instances of objects or
calls to static methods or functions (expressions in general).
That is what constructors are for. I.e. I can understand initializing
static properties (though it gives a lot of potential for weird race
conditions) but for non-statics constructor is exactly the place where
initialization should happen.
--
Stas Malyshev
smalyshev@gmail.com
I'm thinking primarily of the benefit to base or abstract classes. For
base classes which expect certain properties be set, they are exposed to
the danger of remaining unset if the derived class overrides the
constructor without calling the parent.
This solution is analogous to:
class Foo
{
private $timestamp;
private function __construct()
{
$this->timestamp = new DateTime();
$this->init();
}
public function getTimestamp()
{
return $this->timestamp;
}
protected function init()
{
}
}
class Bar extends Foo
{
protected function init()
{
// pseudo constructor of Bar
}
}
The problem now though is that derived classes of Foo are unable to do the
same thing, whereas instantiated default properties would allow:
class Foo
{
private $timestamp = new \DateTime();
public function getTimestamp()
{
return $this->timestamp;
}
}
class Baz extends Foo
{
private $uuid = Uuid::create();
public function getUuid()
{
return $this->uuid;
}
}
class Bar extends Baz
{
public function __construct()
{
// real constructor of Bar
}
}
$bar = new Bar();
var_dump($bar->getTimestamp());
var_dump($bar->getUuid());
With Traits this is even more necessary, because every class (derived or
base) would need to set the properties in each constructor.
On 25 September 2015 at 22:21, Stanislav Malyshev smalyshev@gmail.com
wrote:
Hi!
ability to set default values of properties to instances of objects or
calls to static methods or functions (expressions in general).That is what constructors are for. I.e. I can understand initializing
static properties (though it gives a lot of potential for weird race
conditions) but for non-statics constructor is exactly the place where
initialization should happen.--
Stas Malyshev
smalyshev@gmail.com
Hi!
I'm thinking primarily of the benefit to base or abstract classes. For
Both can have constructors.
base classes which expect certain properties be set, they are exposed to
the danger of remaining unset if the derived class overrides the
constructor without calling the parent.
You should always call the parent ctor. There's pretty much no reason to
ever not to call parent ctor.
--
Stas Malyshev
smalyshev@gmail.com
On Fri, Sep 25, 2015 at 11:53 PM, Stanislav Malyshev
smalyshev@gmail.com wrote:
Hi!
I'm thinking primarily of the benefit to base or abstract classes. For
Both can have constructors.
base classes which expect certain properties be set, they are exposed to
the danger of remaining unset if the derived class overrides the
constructor without calling the parent.You should always call the parent ctor. There's pretty much no reason to
ever not to call parent ctor.--
Stas Malyshev
smalyshev@gmail.com
Since there is no reason not to call parent ctor, maybe PHP should
somehow make every class have default empty ctor, if it doesn't have
one defined already - so you can write automatically
parent::__construct() everywhere?
Regards
Pavel Kouřil
Hi!
Since there is no reason not to call parent ctor, maybe PHP should
somehow make every class have default empty ctor, if it doesn't have
one defined already - so you can write automatically
parent::__construct() everywhere?
I completely agree with you, that's why I submitted
https://wiki.php.net/rfc/default_ctor. Unfortunately, it was rejected.
--
Stas Malyshev
smalyshev@gmail.com
An alternative that rfc might be to add a modifier to ctor, something like.
required public function __construct();
A required function cannot be final, because the intention is to allow it
to be overridden, but it must be called by the child impl at some point.
What do u think?
Hi!
Since there is no reason not to call parent ctor, maybe PHP should
somehow make every class have default empty ctor, if it doesn't have
one defined already - so you can write automatically
parent::__construct() everywhere?I completely agree with you, that's why I submitted
https://wiki.php.net/rfc/default_ctor. Unfortunately, it was rejected.--
Stas Malyshev
smalyshev@gmail.com
By the way, Rasmus updated the RFC quite a bit, you guys may want to
take a look at it again.
An alternative that rfc might be to add a modifier to ctor, something like.
required public function __construct();
A required function cannot be final, because the intention is to allow it
to be overridden, but it must be called by the child impl at some point.
What do u think?
--
Ben Scholzen 'DASPRiD'
Community Review Team Member | mail@dasprids.de
Zend Framework | http://www.dasprids.de
Hi Ben and Rasmus,
On Thu, Jan 7, 2016 at 6:24 PM, Ben Scholzen 'DASPRiD' mail@dasprids.de
wrote:
By the way, Rasmus updated the RFC quite a bit, you guys may want to take
a look at it again.
I just have a couple questions about the rfc, but overall I think its great
and I really hope it makes it into PHP!
Note that the choice of the keyword is to indicate upper bounds is based on
the rejection of perhaps more obvious alternatives - repurposing the
extends or implements keywords would be misleading, since they would work
precisely the same way; worse, permitting both keywords would render
consumer code invalid if an upper bound type provided by a library is
refactored between class and interface. Repurposing instanceof would also
be misleading, since the upper bound is checking the type-hint, not an
instance.
Why not use "as" which is already the keyword used to define aliases?
Probably of the form class foo<DateTimeInterface as DateType> I think this
feels more natural, as its how we do aliasing with a use statement. Also,
this way it follows the same style as other aliases "RealName as Alias".
I'm not saying is doesn't work, but I wonder if you'd considered as and if
so, why you decided against it.
When autoloading is triggered e.g. by a new statement with a generic type,
autoloading is triggered as normal, with only the class-name (without type
parameters) being supplied.
In other words, a statement like new Map<int,string>() will trigger
auto-loading of class Map.
What order are things autoloaded (or does it even matter)? For example,
given the following - does it matter what order things are autoloaded? It
feels like it would but I'm not sure what would get resolved first:
class Gen<IDType, DisplayType, StorageType> {}
class ListGenerator implements HtmlGenerator {}
class FtpWriter extends FileIO {}
new Gen<int, HtmlGenerator, FileIO>(123, new ListGenerator(), new
FtpWriter());
Again, I'm not sure if it matters but would there be any problems (and this
goes to the whole list, since your RFC says you're not a C coder) with the
order of autoloading with relation to resolving validity of types?
In your second example in the Trait section you have:
class Box<T>
{
use Box<T>;
}
I think you meant to say "use Container<T>;" as that is the name of your
trait.
Again, really awesome RFC and I hope it can be implemented and accepted!
~Ryan
Den 2016-01-08 kl. 02:24, skrev Ben Scholzen 'DASPRiD':
By the way, Rasmus updated the RFC quite a bit, you guys may want to
take a look at it again.An alternative that rfc might be to add a modifier to ctor, something
like.required public function __construct();
A required function cannot be final, because the intention is to
allow it
to be overridden, but it must be called by the child impl at some point.
What do u think?
Reading the "Patches and test section" I wonder if some leverage could be
drawn from Hacks implementation of generics?
Regards //Björn Larsson
PS Then we of course have the famous
https://github.com/ircmaxell/PhpGenerics
to lean on ;-)