Hi Stan:

On 01 Aug 2012, at 13:54, Stan Vass wrote:

>> The methods in the class have *always* higher precedence.
>> This is the same 'overriding' behavior used for inheritance.
>> From my personal perspective, changing this would lead to a major 
>> inconsistency with how subclassing works.
> 
> Hi, I've subsequently read your RFC carefully and saw some of those items are 
> by design. However while they're by design, the end result seems rather 
> confusing I should say.
> 
> While I'm glad the RFC was shooting for consistency in general, traits are 
> not subclassing. Therefore aligning the behavior of features for vertical 
> reuse with features for horizontal reuse seems somewhat arbtirary to me.

Horizontal reuse is 'fit into' the hierarchy of things:

  1. super class
  2. horizontal reuse
  3. actual class

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.


> The use cases for overriding methods like this seem sketchy at best. What is 
> the use case, and how are those use cases more important than the confusion 
> caused by allowig this?

I don't see your problem. Can you please elaborate with an example (other than 
your initial one?

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.


>>> 2. Using "as" syntax when importing a trait does NOT rename a method, but 
>>> creates an alias CLONE, the original method still callable.
>>> Proposed behavior: the original name should be only accessible within the 
>>> trait and its methods, not from the class methods or by calling the class 
>>> instance's methods from outside.
> 
>> Again, this happens to be 'by design'.
>> PHP is a rather dynamic language, and we happen to have things like 
>> $c->$foo();
>> where $foo is a string. Renaming is technically not reasonable, and would 
>> also lead to major confusion when metaprogramming is used.

> Can you please explain how are function names by variable at all related to 
> this? $object->foo() and $object->$foo() aren't even related in any way 
> semantically. If a conflict exists while grafting a trait, the original 
> method will be overshadowed silently and the method will be only accessible 
> by the alias. The entire idea of aliasing is to avoid a conflict with an 
> existing method of the same name. While if there's no collision, it's 
> accessible by both. So in practice it works by chance. How is "working by 
> chance" in any way aiding meta programming?

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?


If we use aliasing instead of renaming, we have predictable behavior for all 
options.
foo just happens to be another alias for print.
If print is conflicting with something else, the conflict can be resolved, but 
print() is still going to be called reliably. If you do renaming, it will be 
partial, and you will get foo() called one time, and print() the other time.



> 
>>> 3. Properties silently collide in traits and classes.
>> Please read 
>> https://wiki.php.net/rfc/horizontalreuse#handling_of_propertiesstate 
>> carefully.
>> 
>> Again, this is intended behavior.
>> If you want to be notified of such collisions, please use E_STRICT.
> 
> I've read them carefully now, but there's no solid reason given for this 
> behavior, or why the proper behavior only exists in E_STRICT.
> I can't really see "state is a complex topic" as a reason why trait property 
> collisions are handles inconsistently with method collisions.

Please do me the favor and consult the mailing list archives.
It is all in the various discussions.

There is no proper way to handle state, state requires splitting, merging, and 
what not. None of the research prototypes provides a simple solution.
The solution we have is a 'best effort' solution.
If you can do better, please make a proposal.


>>> 4. The documentation says static propeties can't be defined by traits. Yet 
>>> they can.
>>> 
>>> I don't know what's the bug here: a doc bug, or a code bug. For 
>>> consistency, static properties should work, if instance properties work. 
>>> Nothing is gained supporting it half-way.
> 
>> Could you please point me *exactly* to the paragraph where we have something 
>> written about static properties? I do not see that I wrote anything special 
>> about static properties in the >RFC. And I do not find it in the docs 
>> either. static properties should work like normal properties.
> 
> Sure. From the manual page for traits: "Static variables can be referred to 
> in trait methods, but cannot be defined by the trait."
> This paragraph is then following by a code example using function-static 
> variables as what seems like an example for a replacement for static trait 
> properties, strongly suggesting the former aren't supported. Yet they are.
> 
> The RFC seems to also give examples of method-level static variables, and I 
> honestly can't see how this is related to traits or trait/class-level members 
> at all.

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.

The example code given in the manual is correct. (Example #9 Static Variables)
The section heading is misleading. It is not about static members, and members 
and variables are not synonym. Members are synonym with properties, and 
properties can be static.

Static variables are local to a class, not to a trait.
Traits do not exist at runtime, they are flattened into classes.

With regard to your other mail.
I didn't get a bug report with the keyword trait in it.

If you want me to clarify the confusion, please give me a link.


Best regards
Stefan


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

-- 
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