Hi Stan:

On 01 Aug 2012, at 14:56, Stan Vass wrote:

>> From that follows that traits override the super class's methods.
>> And, conflict resolution is only done between traits, not between a class 
>> and its traits.
>> The class body is a definite thing. Why would you purposefully add something 
>> to a class body that conflicts with a trait?
>> The class needs to know exactly what the traits are doing. There is no 
>> black-box reuse.
> 
> But that's precisely my point. No class would *purposefully* add something to 
> conflict with a trait. Then by your own description the only case is 
> *accidentally* adding something to conflict with it. In such a case why on 
> Earth is it allowed without a fatal error?

Because it is not a matter of horizontal reuse.
Why don't you get a warning when you override an inherited method?
Because that is precisely the way things are supposed to work.

The body of a class is not a trait. These methods are not 'equals'.
I still think that design decision is a sensible one with respect to the rest 
of PHP.



> 
>> The use case for overriding is typically that you got a conflict that you 
>> need to resolve by making a call to both conflicting methods.
>> Consider two traits that happen to provide a log() function, and in the 
>> resulting class you need to call both in all places log() has been called 
>> before.
>> Since the user of these traits is the only place where such semantic is 
>> sensibly defined, the method in the class body is overriding the traits 
>> methods, and can access aliases you
>> introduced for the traits' methods.
> 
> The way it works right now, on conflict, a class may access the trait method 
> via the alias, or its own overriden copy by the conflicting name.
> What is a trait to do? It can't access its own method at all as it doesn't 
> "know" the alias.
> 
> The way this is implemented makes no sense, I'm afraid.

Traits are not classes, traits are supposed to enable composition.
There is no static binding between trait methods. And, yes, this is by design.
It makes sense when you use traits for things you couldn't use classes for.

If you need strong consistency guarantees then you want to use classes.


> 
>> Let's use your example and make something more complex out of it:
>> 
>> trait T {
>>   function bar(){ $this->print();
>>                    $str = 'print';
>>                    $this->$str(); }
>>   function print() { echo 'trait'; }
>> }
>> 
>> > class C {
>>   use T { print as foo; }
>> }
>> 
>> What is supposed to happen in this example if we assume renaming?
>> Would you expect the first function call to print() in bar() to work after 
>> the renaming?
>> Would you expect the second call, using metaprogramming, to work as well?
> 
> It's very simple:
> 
> 1) *only* the original name should work for methods defined in a trait 
> (including metacalls).
> 2) *only* the new name should work from methods defined in the using class 
> (including metacalls).
> 
> Yes, I know: this is a lot more complicated to implement. *But* if we'll take 
> shortcuts in user-facing behavior just because it's simpler to implement, 
> then aliasing should've have never been added at all for 5.4, until it can be 
> implemented reasonably.

So, what is your proposal?


> 
>> If we use aliasing instead of renaming, we have predictable behavior for all 
>> options.
> 
> It's not predictable at all. If the class defines "function print" in your 
> example above, the trait suddenly can't call it's own method anymore! 
> Metacall or not.

It is calling another method instead, indeed. That's composition, and that's 
what traits are designed for.


>> There is no proper way to handle state, state requires splitting, merging, 
>> and what not. None of the research prototypes provides a simple solution.
> 
> State does not require splitting, merging. What does state "splitting" even 
> mean? Here's a very simple design principle here: if you can't guarantee 
> correctness for a behavior, provide a limited behavior, which guarantees 
> correctness. This is how language design works. If there's a conflict, die 
> with a fatal error, make people rename their properties so there's no 
> conflict.

http://scg.unibe.ch/archive/papers/Berg07aStatefulTraits.pdf


> Assuming *silently* that the user is intentionally colliding state variables 
> between traits because he/she wants to merge/split state is insanity IMO.

Instead of calling my insane, I would prefer if you make constructive proposals.
I guess, since you are an expert in language design (and an active user of 
PHP), you are aware of this behavior:

class T1 {
  public function foo() {
    $this->prop = 1;
  }
}

class T2 extends T1 {
  public function bar() {
    $this->prop = 2;
  }
}

$o = new T2;
$o->foo();
$o->bar();

var_dump($o);


What is your point again?

Traits offer already a much stronger safety-net than most other constructs in 
the language. And, thereby are way to strict for some people.

>> The solution we have is a 'best effort' solution.
>> If you can do better, please make a proposal.
> 
> I did in my original email. No property collisions. Fatal errors. It's very 
> simple.

There is nothing simple in PHP...
People don't like fatal errors, especially not for things they intend to just 
work.
From my example above, the kind of guarantees you expect are just not something 
that is part of what PHP is.


>> I assume we are talking about: 
>> http://php.net/manual/en/language.oop5.traits.php
>> 
>> Static variables and members/properties are not related at all. The writer 
>> of the documentation didn't get the wording correct. Please feel free to 
>> submit a patch.
> 
> I've submitted a doc bug. No one want to fix it since they think it's PHP 
> that's wrong, not the manual. I can't do anything more about it.
> Here's the link: https://bugs.php.net/bug.php?id=62156

I don't know who 'they' are, but I am the insane (thanks for that attribute) 
person who wrote the RFCs and the implementation. So, either you accept my 
answer that static properties just work, and you fix the manual by providing a 
greatly appreciate patch,
or, you open a new thread and propose a change, start an RFC, and all that jazz.


Best regards
Stefan


-- 
Stefan Marr
Software Languages Lab
Vrije Universiteit Brussel
Pleinlaan 2 / B-1050 Brussels / Belgium
http://soft.vub.ac.be/~smarr
Phone: +32 2 629 2974
Fax:   +32 2 629 3525


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to