Re: [PHP-DEV] Grafts, Traits, horizontal reuse
Hej Marcus, I like your approach. It is clear and simple. It would probably solve 90% of the cases, where delegation is needed. I want to add that a manually defined method should automatically overwrite a delegated method of the same name. But I also want to bring up two reasonable situations your approach does not cover. Your approach does not allow to delegate only a selection of methods. This makes sense in order to limit the delegation to known functionality. To stick to your example, without selective delegation, new methods added to Counter would be automatically delegated to CounterUser. This might break things. A second situation not covered by your approach is renaming of delegated methods. This can be desirable due to name clashes or name changes for better understandability. Of course there is always the fall back to manually implementing delegation. And your approach alone would already be quite useful syntactic sugar. But additional syntactic sugar for the two situations described above would still be nice :). Another thing. I am not sure if you intended that, but I think delegation should not force using an Interface definition. Interfaces are helpful in combination with type hinting, but for people who prefer duck typing, it is reasonable to not explicitly define them. Let's leave this choice to the people :). Best regards Christopher -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-DEV] Re: Fatal error: Call to a member function on a non-object
Hej, echo $user['fullname']; // no error at all, $user['fullname'] === NULL Shouldn't this at least trigger a Notice? Check your error handling settings, probably warnings/notices are disabled. I now found it in the documentation os the String type http://php.net/language.types.string Note: Accessing variables of other types using [] or {} silently returns NULL. I created a change request: http://bugs.php.net/bug.php?id=46602 Best regards Christopher -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-DEV] Fatal error: Call to a member function on a non-object
Hej, I use PHP 5.2.6. I am refactoring some code to use more object-orientation. I encounter a problem, where the new object-oriented version results in a fatal error, where the old array-oriented version didn't. I fetch records a database. Sometime it happens that a record does not exist anymore. Let's assume it's a user, then $user will be NULL. echo $user['fullname']; // no error at all, $user['fullname'] === NULL Shouldn't this at least trigger a Notice? echo $user-get_fullname(); // Fatal error I agree this should trigger an error, but a Fatal error is a little too much, I think. It terminates the script leaving the html-document incomplete. I would prefer a Warning and NULL instead. Is there any reason against it? Best regards Christopher -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Fatal error: Call to a member function on a non-object
Hi Kalle, I personally don't really mind it, as you got the instanceof and typehinting to check for whenever a variable is an object, so I would say its more of a user design issue. Fatal errors just requires you to refactor your code so your code shouldn't emit such things which I'm alright with. fatal error can also happen caused by a bug. The case described in my Mail is even rather likely. However a fatal error prevents me from handling the error using an error_handler. THAT is the problem. Best regards Christopher -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Grafts, Traits, horizontal reuse
Hej, I really liked to see the Grafts proposal. Well, I'm still in love with the more powerful (because they are interweaveable(breakable)) Traits ;) I don't think there has to be a choice between Grafts and Traits. They serve different purposes and I don't see a reason they shouldn't co-exit. Traits implement code reuse. Code is merged. This is very powerful but can break code. Grafts implement delegation. This is less powerful, but can't break, which makes it preferable, whenever possible. Actually I think this could be a problem for the conciseness of the language. Introducing syntactic sugar for special situations has to be done carefully. In my eyes (well-chosen) syntactic sugar contributes a lot to language conciseness. And every language decision should be done carefully, right? from my perspective forwarding (aka delegation) is a very common concept in OOP which would be worth to be supported by a special syntax. I strongly think so. I like this idea, but there are still some problems to be solved. The major problem with grafts is still the initialization of objects. What to do with constructors which require parameter? Good point. My new suggestion at the end covers it. An other issue I see is the question of introducing to much additional syntax. It could be reduced to something like: private $counter : Counter [use] { //with or without use? public current(); public reset(); } I don't see the above having less syntax than my suggestion. as or : is both syntax. I doubt, I would rather stick to a keyword already in the language in similar semantics. For Comparison, my suggestion was: use Counter as private $counter{ public current(); public reset(); } But now anonymous grafts aren't possible anymore and actually, Grafts had been design without an identity own their own. Yes and I don't think anonymous Grafts would be a good idea. They would make access to grafts complicated and significantly limited including valid use cases. Being explicit instead of implicit helps here in my eyes. On the other hand, this notation could introduce the possibility for advanced initialization: private $cntInitValue; public function __construct($cntValue) { $this-cntInitValue = $cntValue; } private $counter : Counter(cntInitValue) { public current(); public reset(); } I don't think that's a good idea. I admit it's very close to my suggestion, but now it reached a point, where it does something very familiar, namely creating an new object, using a very unfamiliar way and also new syntax. So I make a new suggestion that puts everything much closer to present PHP: class QueueTicketPrinter{ private $counter { public current(); public restart() from reset(); }; public function __construct($cntValue) { $this-counter = new Counter( $cntValue ); } public function takeNumber(){ print 'your number is .$this-current(); $this-counter-inc(); } } And two syntax variants: Variant 1: private $counter use { public current(); reset() as public restart(); }; Variant 2: private $counter delegate { public current(); public restart() to reset(); }; This suggestion requires a new runtime Error/Exception for cases when a method of QueueTicketPrinter is called that is delegated to a method that $counter does not implement. Every time you just like to compose a class from different kinds of behaviors Traits are superior. More powerful yes, superior no. Delegation and inheritance (counting traits as a variant of inheritance) both allow functionality re-use but both also resemble a trade-off between flexibility and breakability. Inheritance is more flexible, but can easily break, especially when inheritance structures grow. Delegation is less flexible, but can't break (from reuse), even in large structures. So both are justified. Best regards Christopher P.S. I should mention that I do not have any insight of the actual implementation of PHP. So if I suggest something insensibly hard to implement, just shout :). -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-DEV] Traits,Grafts, horizontal reuse
Hej everybody, I had a chat with Stefan about his Traits/Grafts RFC and he suggested we should rather continue a discussion here. I really liked to see the Grafts proposal. In traits and regular inheritance the implementation code of several entities is somehow mixed and as a result one entities code can break another entities code. The great thing about Grafts is that the implementation is not mixed. Grafts are completely independent entities with their own state. I think in many cases where inheritance or traits seem tempting, complete encapsulation is actually the cleaner solution. The Grafts proposal, however, suffered a little from being born out of traits, I think. Something similar to Grafts is already possible in current php, but it is not very beautiful. If we start from there however, Grafts could become very helpful syntactic sugar. Let's look at current PHP first: class Counter { private $cnt = 0; public function inc() { $this-cnt++; } public function reset() { $this-cnt = -1; $this-inc(); } } class TakeANumberForTheQueue{ , so this is one , but I think it could be even better when it was much closer to current PHP than suggested in the RFC. Let me explain what I mean. Graft were born out of the idea of traits. Traits are a variant of inheritance and a trade-off between single and multiple inheritance with the goal to reduce code duplication. The problem with inheritance is that code can break because code from different classes (or traits) is mixed together interfering with Either kind of inheritance can be very tempting to be used to reuse functionality. implement code reuse. Code reuse is tempting but often enough it is not really necessary to reuse the comes from the wrong direction and didn't go far enough. Traits conquer the lacks of single inheritance without giving the full power of multiple inheritance. Traits are still sort of inheritance. When a class uses a trait the trait's code can access class implementation details and vice-vera. This might come in handy at some point, however I personally lack a good use case for now. Can somebody provide a sensible use case for traits? A Problem with code inheritance (single, traits, whatever) is that the possibility to use inheritance seduces to use it even when it is not necessarily needed. Stefan's Counter example is a good one. What I find even more promising than Traits are Grafts. I know Grafts where born out of the traits idea, but I want to try to put them idea a little forward and separate the from the traits idea even stronger than Stefan already did. Why do we want Grafts? Because inheritance can be a problem -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-DEV] gnaaa. Hit the submit button too early.
Gnaaa. Hit the submit button too early. Excuse the rubbish. I will post the correct mail in a moment. Christopher -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-DEV] Grafts, Traits, horizontal reuse
Hej everybody, I had a chat with Stefan about his Traits/Grafts RFC and he suggested we should rather continue a discussion here. I really liked to see the Grafts proposal. In traits and regular inheritance the implementation code of several entities is somehow mixed and as a result one entities code can break another entities code. The great thing about Grafts is that the implementation is not mixed. Grafts are completely encapsulated entities with their own state. I think in many cases where inheritance or traits seem tempting, complete encapsulation is actually the cleaner solution. The Grafts proposal, however, suffered a little from being born out of traits, I think. Something similar to Grafts is already possible in current php, but it is not very beautiful. If we start from there however, Grafts could become very helpful syntactic sugar. Let's look at current PHP first: class Counter { private $cnt = 0; public function inc() { $this-cnt++; return $this; } public function reset() { $this-cnt = -1; $this-inc(); return $this; } public function current(){ return $this-cnt; return $this; } } class QueueTicketPrinter{ private $counter; public __construct(){ $this-counter = new Counter(); } public function takeNumber(){ print 'your number is .$this-counter-current(); $this-counter-inc(); } public function current(){ $this-counter-current(); } public function reset(){ $this-counter-reset(); } } This is a lot of code in QueueTicketPrinter for that it mostly reuses Counter. Grafts as syntactic sugar could make it look as short as: class QueueTicketPrinter{ use Counter as private $counter{ public current(); public reset(); } public function takeNumber(){ print 'your number is .$this-counter-current(); $this-counter-inc(); } } However a problem remains. The methods of counter return $this (aka implement a fluent interface). One idea that came to my mind to solve this problem: PHP could provide a keyword fluent that replaces a methods return value to form a fluent interface i.e. return $this: class QueueTicketPrinter{ use Counter as private $counter{ public fluent current(); public fluent reset(); } public function takeNumber(){ print 'your number is .$this-counter-current(); $this-counter-inc(); } } The keyword fluent ignores whatever value the Counter function may return and returns an the instance of QueueTicketPrinter instead. Finally, can somebody provide a sensible use case for traits, that cannot be solved with Grafts? I am sure there is, but I am currently lacking one. Cheers Christopher P.S. Hope that stupid post before does not make me seem too much like it ;). -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php