# Traits and Properties

- Thread: https://externals.io/message/51007
- Original archive: https://news-web.php.net/php.internals/51007
- Started by Stefan Marr on 2010-12-11T16:47:03+00:00
- Messages: 43
- RFC: Constants in Traits (Implemented (PHP 8.2)) — https://externals.io/rfc/constants_in_traits.md
- Page 1 of 2: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/51007.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #51007 — Stefan Marr — 2010-12-11T16:47:03+00:00

URL: https://externals.io/message/51007#51007

Hi:

Traits do not provide any special provisioning for handling properties, especially, there is no language solution for handling colliding property names.
The current solution/idiom for handling state safely in a trait is to use either abstract set/get methods or an abstract get that returns a reference to the property in the class.

However, at the moment it is possible to define properties in a trait:

trait Foo {
 private $a;
 public  $foo;
}

For the moment, that information is completely ignored, thus:

class Bar {
 use Foo;
}
property_exists('Bar', 'a') === false


Well, and that is a rather inconsistent status-quo.

I would like to have that fixed in one or another way.

One possibility would be to forbid property definition in a trait altogether.
That reduces a bit the possibility to have wrong expectations about properties, however, the dynamic property creation is still possible.

Another way would be to merge the properties in the composing class.
The question here would be how to treat visibility modifiers: how to merge public and private, should it result in public, or private?
And, to discorage users to go this way, should there be a STRICT notice? Options here are a notice whenever a property is defined in a trait, or whenever properties are silently merged.


Comments very welcome.

Thanks
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

---

## #51008 — Nathan Nobbe — 2010-12-11T18:35:01+00:00

URL: https://externals.io/message/51007#51008 · In reply to: #51007

> Hi:
>
> Traits do not provide any special provisioning for handling properties,
> especially, there is no language solution for handling colliding property
> names.
> The current solution/idiom for handling state safely in a trait is to use
> either abstract set/get methods or an abstract get that returns a reference
> to the property in the class.
>
> However, at the moment it is possible to define properties in a trait:
>
> trait Foo {
>  private $a;
>  public  $foo;
> }
>
> For the moment, that information is completely ignored, thus:
>
> class Bar {
>  use Foo;
> }
> property_exists('Bar', 'a') === false
>
>
> Well, and that is a rather inconsistent status-quo.
>
> I would like to have that fixed in one or another way.
>
> One possibility would be to forbid property definition in a trait
> altogether.
> That reduces a bit the possibility to have wrong expectations about
> properties, however, the dynamic property creation is still possible.
>
> Another way would be to merge the properties in the composing class.
> The question here would be how to treat visibility modifiers: how to merge
> public and private, should it result in public, or private?
> And, to discorage users to go this way, should there be a STRICT notice?
> Options here are a notice whenever a property is defined in a trait, or
> whenever properties are silently merged.
>

I would prefer they be definable within traits and merged into classes,
otherwise traits will not have the chance to be self-contained entities of
reusable logic.  Also, I think merging them in is consistent with the
treatment given to methods as they pertain to traits.

As I'm sure you know:
<?php
class A {
  use SomeTrait;
}

trait SomeTrait {
  public function traitMethod() {}
}

method_exists('A', 'traitMethod') === true;
?>

Regarding visibility modifiers, why not carry them over from the trait
directly, private in the trait definition results in private in the class
definition.  Lastly, I'm not sure why you would want to discourage this
usage, I would plan on adding properties in traits myself.

-nathan

---

## #51009 — Sebastian Bergmann — 2010-12-11T18:36:03+00:00

URL: https://externals.io/message/51007#51009 · In reply to: #51007

> Another way would be to merge the properties in the composing class.

  +1

> The question here would be how to treat visibility modifiers

  One option would be to only allow private. That way only methods from
  the trait would have access and collisions could be prevented.

> And, to discorage users to go this way, should there be a STRICT
> notice?

  If you want to discourage attribute declaration in a trait, don't
  allow it at all.

-- 
Sebastian Bergmann                    Co-Founder and Principal Consultant
http://sebastian-bergmann.de/                           http://thePHP.cc/

---

## #51010 — Pierre Joye — 2010-12-11T22:13:12+00:00

URL: https://externals.io/message/51007#51010 · In reply to: #51007

hi,

Would it be possible to somehow document what you are discussing here?
It is not too easy to keep track of all discussions about traits
(along other things). Maybe in draft RFC or a simple page in the wiki.
Doing so will help to have a quick view about the open questions or
recent changes/propositions.

Thanks!


> Hi:
>
> Traits do not provide any special provisioning for handling properties, especially, there is no language solution for handling colliding property names.
> The current solution/idiom for handling state safely in a trait is to use either abstract set/get methods or an abstract get that returns a reference to the property in the class.
>
> However, at the moment it is possible to define properties in a trait:
>
> trait Foo {
>  private $a;
>  public  $foo;
> }
>
> For the moment, that information is completely ignored, thus:
>
> class Bar {
>  use Foo;
> }
> property_exists('Bar', 'a') === false
>
>
> Well, and that is a rather inconsistent status-quo.
>
> I would like to have that fixed in one or another way.
>
> One possibility would be to forbid property definition in a trait altogether.
> That reduces a bit the possibility to have wrong expectations about properties, however, the dynamic property creation is still possible.
>
> Another way would be to merge the properties in the composing class.
> The question here would be how to treat visibility modifiers: how to merge public and private, should it result in public, or private?
> And, to discorage users to go this way, should there be a STRICT notice? Options here are a notice whenever a property is defined in a trait, or whenever properties are silently merged.
>
>
> Comments very welcome.
>
> Thanks
> 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
>
>
> --
> 
> 
>
>



-- 
Pierre

@pierrejoye | http://blog.thepimp.net | http://www.libgd.org

---

## #51011 — Stefan Marr — 2010-12-11T23:31:52+00:00

URL: https://externals.io/message/51007#51011 · In reply to: #51010

Hi Pierre:



> hi,
> 
> Would it be possible to somehow document what you are discussing here?
> It is not too easy to keep track of all discussions about traits
> (along other things). Maybe in draft RFC or a simple page in the wiki.
> Doing so will help to have a quick view about the open questions or
> recent changes/propositions.
Yes, I try to keep track of all this in the RFC:
  http://wiki.php.net/rfc/horizontalreuse?do=revisions

The current status of the property behavior is not yet documented explicitly, it is only implied since it is not handled at all...
And, it is the only open question that 'needs' to be solved since it is an inconsistency.
For instance the 'require Interface' is more like an additional feature.

Best regards
Stefan


> 
> Thanks!
> 
> 
> > […]
> 
> 
> 
> -- 
> Pierre
> 
> @pierrejoye | http://blog.thepimp.net | http://www.libgd.org

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

---

## #51012 — Stefan Marr — 2010-12-12T00:24:20+00:00

URL: https://externals.io/message/51007#51012 · In reply to: #51009

Hi Sebastian:


> > […]
> 
> If you want to discourage attribute declaration in a trait, don't
> allow it at all.
Not allowing it is not an option as far as I can tell.

You can always use dynamically defined properties in a method.
Changing that would change the whole character of PHP.
Then we would have two types of methods, methods that are defined in the class directly and can do what ever they want with properties, and methods from traits which are restricted and can't access any state.

I think, that would be to much penalty for all the valid use cases where a naive property usage in a trait is still just fine.

Best regards
Stefan


> 
> -- 
> Sebastian Bergmann                    Co-Founder and Principal Consultant
> http://sebastian-bergmann.de/                           http://thePHP.cc/
> 
> -- 
> 
> 
> 

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

---

## #51013 — Sebastian Bergmann — 2010-12-12T09:02:30+00:00

URL: https://externals.io/message/51007#51013 · In reply to: #51012

> > […]
> Not allowing it is not an option as far as I can tell.

  Good! :-)

-- 
Sebastian Bergmann                    Co-Founder and Principal Consultant
http://sebastian-bergmann.de/                           http://thePHP.cc/

---

## #51014 — Stefan Marr — 2010-12-12T10:59:38+00:00

URL: https://externals.io/message/51007#51014 · In reply to: #51008

Hi Nathan:



> Regarding visibility modifiers, why not carry them over from the trait directly, private in the trait definition results in private in the class definition.

The problem will be hopefully more clear in the following example:

trait StateMachineDoor {
  private $currentState;
  public function open() {....}
}

trait StateMachineElevator {
  public $currentState;
  public function callElevator() { ... }
}

These two traits are not compatible since currentState has different semantics in both traits.
With the current design of traits, there is no language solution to this problem.

The suggestions to avoid the problem are to use better names like $currentDoorState and $currentElevatorState, or to rely on accessors which is currently the only variant in which the programmer will notice that there is an incompatibility:

trait StateMachineDoor {
  abstract function &getCurrentState();
  public function open() {....}
}

trait StateMachineElevator {
  abstract function &getCurrentState();
  public function callElevator() { ... }
}

However, you might have a different situation, one where the traits are composable with respect to their state, i.e., they need to work on the same state:

trait OutputIterator {
  public $array;  // not sure why that is public here, but the implementor chose to make it public...
  public function printNext() {...}
} 

trait SortArray {
  private $array; // this developer chose to make the array private, for what ever reason...
  public function doSort() { ... }
}

I hope that makes the possible situations clear: state can either be composable or not, that really depends
on the trait. And there is no language solution for it build in at the moment.

So, back to my original question:

class SomethingOutputableAndSortable {
  use OutoutIterator, SortArray;
}

What is the visibility of $array supposed to be in this class? private or public?

And further, in the very first example of this mail, ideally there should be some warning, however, that warning would be annoying for the last example, since here the state does not collide...

Best regards
Stefan

PS: there has been discussion on stateful traits before, but the language solutions to that where considered to complex.

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

---

## #51018 — Richard Quadling — 2010-12-13T13:13:22+00:00

URL: https://externals.io/message/51007#51018 · In reply to: #51007

> Hi:
>
> Traits do not provide any special provisioning for handling properties, especially, there is no language solution for handling colliding property names.
> The current solution/idiom for handling state safely in a trait is to use either abstract set/get methods or an abstract get that returns a reference to the property in the class.
>
> However, at the moment it is possible to define properties in a trait:
>
> trait Foo {
>  private $a;
>  public  $foo;
> }
>
> For the moment, that information is completely ignored, thus:
>
> class Bar {
>  use Foo;
> }
> property_exists('Bar', 'a') === false
>
>
> Well, and that is a rather inconsistent status-quo.
>
> I would like to have that fixed in one or another way.
>
> One possibility would be to forbid property definition in a trait altogether.
> That reduces a bit the possibility to have wrong expectations about properties, however, the dynamic property creation is still possible.
>
> Another way would be to merge the properties in the composing class.
> The question here would be how to treat visibility modifiers: how to merge public and private, should it result in public, or private?
> And, to discorage users to go this way, should there be a STRICT notice? Options here are a notice whenever a property is defined in a trait, or whenever properties are silently merged.
>
>
> Comments very welcome.
>
> Thanks
> Stefan

From the rfc [1], "A Trait is similar to a class, but only intended to
group functionality".

I'm guessing that says it all. A trait has no properties.

But.

If properties are to be added to a trait, I think that should come as
a further enhancement and let traits start out as "methods only".

If a trait is properties, then also supporting constants and the other
sort of set/get properties would provide a strong level of
consistency. If I can put it in a class, I can put it in a trait.

As visibility on the traits methods can be manipulated via the
aliasing mechanism, so should any visibility to a property.

Richard.

[1] http://wiki.php.net/rfc/horizontalreuse
-- 
Richard Quadling
Twitter : EE : Zend
@RQuadling : e-e.com/M_248814.html : bit.ly/9O8vFY

---

## #51019 — Richard Quadling — 2010-12-13T13:31:43+00:00

URL: https://externals.io/message/51007#51019 · In reply to: #51011

> The current status of the property behavior is not yet documented explicitly

On the assumption that traits WILL include properties (with
visibility) and aliasing can do all its magic, how would the situation
be handled where multiple traits define shared properties.

I've not got a use case, but say trait1 and trait2 both define the
same property.

Assuming name conflicts are handled via aliasing, then the property
needs to alert the aliasing code that this property is a non
conflicting property. All traits wanting to access the shared property
would have to reveal their intentions.

I can think of 2 ways to handle this (but I'm no genius here, so take
them apart at your pleasure).

1 - The trait's code marks shared properties with a keyword (shared,
common, virtual, something). During incorporation of the trait into
the main class, any marked properties are checked for visibility only.
2 - The trait's code uses a &$property. The fact that this is a
reference would require the creation of the property (if it doesn't
already exist) whilst the trait is being compiled into the main class.
I'd guess this would be the least difficult to implement, but I know
squat about this.

I'm guessing the order of handling the traits would be significant here.

Trait1 uses $property, Trait2 uses $property - conflict. Must be
resolved by aliasing or an error.
Trait1 uses &$property, Trait2 uses &$property - all ok. Trait1 wants
access a non existing property, so one is created. Trait2 is sharing
the now pre-existing property.
Trait1 uses &$property, Trait2 uses $property - conflict. Trait1 wants
access a non existing property, so one is created. Trait2's $property
must be aliased to an error.
Trait1 uses $property, Trait2 uses &$property - all ok. Trait1's
$property is added as expected. Trait2 is sharing the now pre-existing
property.

Richard.


-- 
Richard Quadling
Twitter : EE : Zend
@RQuadling : e-e.com/M_248814.html : bit.ly/9O8vFY

---

## #51020 — Stefan Marr — 2010-12-13T16:02:13+00:00

URL: https://externals.io/message/51007#51020 · In reply to: #51018

Hi Richard:



> From the rfc [1], "A Trait is similar to a class, but only intended to
> group functionality".
> 
> I'm guessing that says it all. A trait has no properties.

It is really a practical concern of language consistency for the moment.
I am not talking about any fancy new language feature to handle state.

At the moment, I am just concerned with examples like the following:

trait Foo {
  function bar() {
    $this->baz = 'abcd';
  }
}

If that example becomes more complex, I would consider it to be good software engineering practice to document the usage of $this->baz and its semantic.

For classes this is usually done by explicitly naming the property in the class body.

At the moment, there is nothing which hinders you in doing that for a trait.

However, since traits do not provide any safety provisioning for state, i.e., there is no collision handling for properties, the question is, how do we either promote to use explicit accessors or how do we deal with the inevitable and certainly justified use of properties in one or the other way.

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

---

## #51021 — Stefan Marr — 2010-12-13T16:16:42+00:00

URL: https://externals.io/message/51007#51021 · In reply to: #51019

Hi Richard:



> 
> > […]
> 
> On the assumption that traits WILL include properties (with
> visibility) and aliasing can do all its magic, how would the situation
> be handled where multiple traits define shared properties.
> 
> I've not got a use case, but say trait1 and trait2 both define the
> same property.
> 
> Assuming name conflicts are handled via aliasing, then the property
> needs to alert the aliasing code that this property is a non
> conflicting property.
Just to emphasize this another time: aliasing is no magic, it is NOT renaming.
(And it is only supported for methods.)

The important implication here is, that aliasing is only useful from the viewpoint of the composing class.
Form the trait's perspective, aliasing does not have any effect.

Aliasing can be used to make a function accessible that has a naming conflict with another function.
It enables composition of traits, but does not do anything with regard which function names a trait-function calls. In PHP all function names are late bound, there is no inner binding between functions in traits.

Hope that clarifies what I perceived as a misconception.



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

---

## #51024 — Larry Garfield — 2010-12-14T02:27:59+00:00

URL: https://externals.io/message/51007#51024 · In reply to: #51020

> However, since traits do not provide any safety provisioning for state,
> i.e., there is no collision handling for properties, the question is, how
> do we either promote to use explicit accessors or how do we deal with the
> inevitable and certainly justified use of properties in one or the other
> way.
> 
> Best regards
> Stefan

Thinking about it, I'm not sure that accessors are really a solid solution 
either.

Behavior has to have something to behave on.  So whether you have 

$this->foo 

or

$foo = $this->getFoo();
// Do stuff with $foo
$this->setFoo($foo);

You still have a dependency that the composing class have either a property 
named $foo or a pair of (frankly pointless) get/set methods.

So either a composing class needs to know about the internal implementation 
details of a trait (what it calls variables inside of a method) so that it can 
provide what the trait needs, or a trait needs to be able to carry around its 
own implementation details.

So it seems to me like we can't not let traits carry properties, which means 
we need to resolve them some how.

--Larry Garfield

---

## #51055 — Stefan Marr — 2010-12-16T15:25:42+00:00

URL: https://externals.io/message/51007#51055 · In reply to: #51007

Hi:

From my point of view the right thing to do with regard to properties is defined in the test cases below.

The rational behind providing this semantics is based on the fact that PHP allows to define properties dynamically anyway, so there is no way around properties.
However, there should be a way that a developer can notice that the code might not behave as expected in the composed class.

It is true that behavior needs state to operate on, however, accessors are a common pattern and fully supported by traits. Furthermore, traits are not supposed to replace classes, and when a trait does more than just providing code that is to be easily reused, then the designed should ask the question whether that is not actually a class, which then provides the necessary guarantees to enforce the invariances the code expects.

Thus, I would like to keep traits as a lightweight concept for code reuse.

Best regards
Stefan

--TEST--
Conflicting properties should result in a notice.
Property use is discorage for traits that are supposed to enable maintainable
code reuse. Accessor methods are the language supported idiom for this.
--FILE--
<?php
error_reporting(E_ALL);

trait THello1 {
  public $foo;
}

trait THello2 {
  private $foo;
}

class TraitsTest {
	use THello1;
	use THello2;
}

var_dump(property_exists('TraitsTest', 'foo'));
?>
--EXPECTF--	
Notice: Trait THello1 and THello2 define the same property in the composition of TraitsTest. This might be incompatible, to improve maintainability consider using accessor methods instead. Class was composed in %s on line %d.

bool(true)




--TEST--
Non-conflicting properties should work just fine.
--FILE--
<?php
error_reporting(E_ALL);

trait THello1 {
  public $hello = "hello";
}

trait THello2 {
  private $world = "World!";
}

class TraitsTest {
	use THello1;
	use THello2;
	function test() {
	    echo $this->hello . ' ' . $this->world;
	}
}

var_dump(property_exists('TraitsTest', 'hello'));
var_dump(property_exists('TraitsTest', 'world'));

$t = new TraitsTest;
$t->test();
?>
--EXPECTF--	
bool(true)
bool(true)

hello World!


--TEST--
Conflicting properties with different visibility modifiers should be merged
to the most restrictive modifier.
--FILE--
<?php
error_reporting(E_ALL);

trait THello1 {
  public $hello;
}

trait THello2 {
  private $hello;
}

class TraitsTest {
	use THello1;
	use THello2;
}

$t = new TraitsTest;
$t->hello = "foo";
?>
--EXPECTF--	
Fatal error: Cannot access private property TraitsTest::$foo in %s on line %d



> Hi:
> 
> Traits do not provide any special provisioning for handling properties, especially, there is no language solution for handling colliding property names.
> The current solution/idiom for handling state safely in a trait is to use either abstract set/get methods or an abstract get that returns a reference to the property in the class.
> 
> However, at the moment it is possible to define properties in a trait:
> 
> trait Foo {
> private $a;
> public  $foo;
> }
> 
> For the moment, that information is completely ignored, thus:
> 
> class Bar {
> use Foo;
> }
> property_exists('Bar', 'a') === false
> 
> 
> Well, and that is a rather inconsistent status-quo.
> 
> I would like to have that fixed in one or another way.
> 
> One possibility would be to forbid property definition in a trait altogether.
> That reduces a bit the possibility to have wrong expectations about properties, however, the dynamic property creation is still possible.
> 
> Another way would be to merge the properties in the composing class.
> The question here would be how to treat visibility modifiers: how to merge public and private, should it result in public, or private?
> And, to discorage users to go this way, should there be a STRICT notice? Options here are a notice whenever a property is defined in a trait, or whenever properties are silently merged.
> 
> 
> Comments very welcome.
> 
> Thanks
> 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
> 
> 
> --
> 
> 
> 

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

---

## #51056 — Sebastian Bergmann — 2010-12-16T15:59:03+00:00

URL: https://externals.io/message/51007#51056 · In reply to: #51055

Am 16.12.2010 16:25, schrieb Stefan Marr:
> From my point of view the right thing to do with regard to
> properties is defined in the test cases below.

 +1

-- 
Sebastian Bergmann                    Co-Founder and Principal Consultant
http://sebastian-bergmann.de/                           http://thePHP.cc/

---

## #51057 — Benjamin Eberlei — 2010-12-16T16:01:03+00:00

URL: https://externals.io/message/51007#51057 · In reply to: #51055

I like it,

additionally if you want to prevent conflicts from the start you can
always go and define prefixed property names like below and use a getter to
access them conveniently.

trait Foo
{
    private $Foo_prop;

    public function getProp()
    {
        return $this->Foo_prop;
    }
}

I am really looking forward to traits in 5.4!

greetings,
Benjamin

On Thu, 16 Dec 2010 16:25:42 +0100, Stefan Marr <php@stefan-marr.de>
wrote:
> Hi:
> 
> From my point of view the right thing to do with regard to properties is
> defined in the test cases below.
> 
> The rational behind providing this semantics is based on the fact that
PHP
> allows to define properties dynamically anyway, so there is no way
around
> properties.
> However, there should be a way that a developer can notice that the code
> might not behave as expected in the composed class.
> 
> It is true that behavior needs state to operate on, however, accessors
are
> a common pattern and fully supported by traits. Furthermore, traits are
not
> supposed to replace classes, and when a trait does more than just
providing
> code that is to be easily reused, then the designed should ask the
question
> whether that is not actually a class, which then provides the necessary
> guarantees to enforce the invariances the code expects.
> 
> Thus, I would like to keep traits as a lightweight concept for code
reuse.
> 
> Best regards
> Stefan
> 
> --TEST--
> Conflicting properties should result in a notice.
> Property use is discorage for traits that are supposed to enable
> maintainable
> code reuse. Accessor methods are the language supported idiom for this.
> --FILE--
> <?php
> error_reporting(E_ALL);
> 
> trait THello1 {
>   public $foo;
> }
> 
> trait THello2 {
>   private $foo;
> }
> 
> class TraitsTest {
> 	use THello1;
> 	use THello2;
> }
> 
> var_dump(property_exists('TraitsTest', 'foo'));
> ?>
> --EXPECTF--	
> Notice: Trait THello1 and THello2 define the same property in the
> composition of TraitsTest. This might be incompatible, to improve
> maintainability consider using accessor methods instead. Class was
composed
> in %s on line %d.
> 
> bool(true)
> 
> 
> 
> 
> --TEST--
> Non-conflicting properties should work just fine.
> --FILE--
> <?php
> error_reporting(E_ALL);
> 
> trait THello1 {
>   public $hello = "hello";
> }
> 
> trait THello2 {
>   private $world = "World!";
> }
> 
> class TraitsTest {
> 	use THello1;
> 	use THello2;
> 	function test() {
> 	    echo $this->hello . ' ' . $this->world;
> 	}
> }
> 
> var_dump(property_exists('TraitsTest', 'hello'));
> var_dump(property_exists('TraitsTest', 'world'));
> 
> $t = new TraitsTest;
> $t->test();
> ?>
> --EXPECTF--	
> bool(true)
> bool(true)
> 
> hello World!
> 
> 
> --TEST--
> Conflicting properties with different visibility modifiers should be
merged
> to the most restrictive modifier.
> --FILE--
> <?php
> error_reporting(E_ALL);
> 
> trait THello1 {
>   public $hello;
> }
> 
> trait THello2 {
>   private $hello;
> }
> 
> class TraitsTest {
> 	use THello1;
> 	use THello2;
> }
> 
> $t = new TraitsTest;
> $t->hello = "foo";
> ?>
> --EXPECTF--	
> Fatal error: Cannot access private property TraitsTest::$foo in %s on
line
> %d
> 
> 
> 
> > […]
property
> > […]
notice?
> > […]
> 
> -- 
> 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

---

## #51060 — Matthew Weier O'Phinney — 2010-12-16T17:49:07+00:00

URL: https://externals.io/message/51007#51060 · In reply to: #51055

> From my point of view the right thing to do with regard to properties
> is defined in the test cases below.
>
> The rational behind providing this semantics is based on the fact that
> PHP allows to define properties dynamically anyway, so there is no way
> around properties.  However, there should be a way that a developer
> can notice that the code might not behave as expected in the composed
> class.

+1

The test cases you include are exactly how I would expect traits to work
with regards to properties.

-- 
Matthew Weier O'Phinney
Project Lead            | matthew@zend.com
Zend Framework          | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc

---

## #51062 — Patrick ALLAERT — 2010-12-16T21:05:24+00:00

URL: https://externals.io/message/51007#51062 · In reply to: #51055

2010/12/16 Stefan Marr <php@stefan-marr.de>:
> Hi:
>
> From my point of view the right thing to do with regard to properties is defined in the test cases below.
>
> The rational behind providing this semantics is based on the fact that PHP allows to define properties dynamically anyway, so there is no way around properties.
> However, there should be a way that a developer can notice that the code might not behave as expected in the composed class.
>
> It is true that behavior needs state to operate on, however, accessors are a common pattern and fully supported by traits. Furthermore, traits are not supposed to replace classes, and when a trait does more than just providing code that is to be easily reused, then the designed should ask the question whether that is not actually a class, which then provides the necessary guarantees to enforce the invariances the code expects.
>
> Thus, I would like to keep traits as a lightweight concept for code reuse.
>
> Best regards
> Stefan
>
> --TEST--
> Conflicting properties should result in a notice.
> Property use is discorage for traits that are supposed to enable maintainable
> code reuse. Accessor methods are the language supported idiom for this.
> --FILE--
> <?php
> error_reporting(E_ALL);
>
> trait THello1 {
>  public $foo;
> }
>
> trait THello2 {
>  private $foo;
> }
>
> class TraitsTest {
>        use THello1;
>        use THello2;
> }
>
> var_dump(property_exists('TraitsTest', 'foo'));
> ?>
> --EXPECTF--
> Notice: Trait THello1 and THello2 define the same property in the composition of TraitsTest. This might be incompatible, to improve maintainability consider using accessor methods instead. Class was composed in %s on line %d.

In this test, you might want to display some text before the
 `var_dump()` (or alternatively to hardcode the line number on last line)
to ensure it is the `property_exists()` function call or the class
definition which would create such a notice.

Regards,
Patrick

-- 
Patrick Allaert
---
http://code.google.com/p/peclapm/ - Alternative PHP Monitor

---

## #51066 — larry@garfieldtech.com — 2010-12-16T22:31:12+00:00

URL: https://externals.io/message/51007#51066 · In reply to: #51055

I am fine with this approach, with 2 caveats:

- If you actually do want to make two traits use the same property, it 
looks like the answer here is "Either have no property and demand the 
existence of an accessor that returns by reference, or you can't write 
E_NOTICE-safe code".  Is that true?

- When the visibility collides, should we be folding to the most 
restrictive or least restrictive?  I'm not sure myself; I'm more 
interested in your reasoning for going for most-restrictive.

--Larry Garfield


> Hi:
>
>  From my point of view the right thing to do with regard to properties is defined in the test cases below.
>
> The rational behind providing this semantics is based on the fact that PHP allows to define properties dynamically anyway, so there is no way around properties.
> However, there should be a way that a developer can notice that the code might not behave as expected in the composed class.
>
> It is true that behavior needs state to operate on, however, accessors are a common pattern and fully supported by traits. Furthermore, traits are not supposed to replace classes, and when a trait does more than just providing code that is to be easily reused, then the designed should ask the question whether that is not actually a class, which then provides the necessary guarantees to enforce the invariances the code expects.
>
> Thus, I would like to keep traits as a lightweight concept for code reuse.
>
> Best regards
> Stefan
>
> --TEST--
> Conflicting properties should result in a notice.
> Property use is discorage for traits that are supposed to enable maintainable
> code reuse. Accessor methods are the language supported idiom for this.
> --FILE--
> <?php
> error_reporting(E_ALL);
>
> trait THello1 {
>    public $foo;
> }
>
> trait THello2 {
>    private $foo;
> }
>
> class TraitsTest {
> 	use THello1;
> 	use THello2;
> }
>
> var_dump(property_exists('TraitsTest', 'foo'));
> ?>
> --EXPECTF--	
> Notice: Trait THello1 and THello2 define the same property in the composition of TraitsTest. This might be incompatible, to improve maintainability consider using accessor methods instead. Class was composed in %s on line %d.
>
> bool(true)
>
>
>
>
> --TEST--
> Non-conflicting properties should work just fine.
> --FILE--
> <?php
> error_reporting(E_ALL);
>
> trait THello1 {
>    public $hello = "hello";
> }
>
> trait THello2 {
>    private $world = "World!";
> }
>
> class TraitsTest {
> 	use THello1;
> 	use THello2;
> 	function test() {
> 	    echo $this->hello . ' ' . $this->world;
> 	}
> }
>
> var_dump(property_exists('TraitsTest', 'hello'));
> var_dump(property_exists('TraitsTest', 'world'));
>
> $t = new TraitsTest;
> $t->test();
> ?>
> --EXPECTF--	
> bool(true)
> bool(true)
>
> hello World!
>
>
> --TEST--
> Conflicting properties with different visibility modifiers should be merged
> to the most restrictive modifier.
> --FILE--
> <?php
> error_reporting(E_ALL);
>
> trait THello1 {
>    public $hello;
> }
>
> trait THello2 {
>    private $hello;
> }
>
> class TraitsTest {
> 	use THello1;
> 	use THello2;
> }
>
> $t = new TraitsTest;
> $t->hello = "foo";
> ?>
> --EXPECTF--	
> Fatal error: Cannot access private property TraitsTest::$foo in %s on line %d
>
> 
>
> > […]

---

## #51072 — Stefan Marr — 2010-12-18T15:29:16+00:00

URL: https://externals.io/message/51007#51072 · In reply to: #51024

Hi Larry:



> I am fine with this approach, with 2 caveats:
> 
> - If you actually do want to make two traits use the same property, it looks like the answer here is "Either have no property and demand the existence of an accessor that returns by reference, or you can't write E_NOTICE-safe code".  Is that true?
Yes, that is the tradeoff, perhaps the notice could be restricted be shown in strict-mode only.

The manual says the following about E_STRICT, so it seems to fit, but I am not sure about the usual usage of `E_STRICT` throughout the engine.

Manual:
> Note:
> In PHP 5 a new error level `E_STRICT` is available. As `E_STRICT` is not included within `E_ALL` you have to explicitly enable this kind of error level. Enabling `E_STRICT` during development has some benefits. STRICT messages will help you to use the latest and greatest suggested method of coding, for example warn you about using deprecated functions.



> - When the visibility collides, should we be folding to the most restrictive or least restrictive?  I'm not sure myself; I'm more interested in your reasoning for going for most-restrictive.
So, in general, I think, there is no 'right thing' to do here, because the definitions seem to be incompatible but that is only decidable at the application-level.

There is another, related, edge-case in the test case below.
In the test we have different initial values for the properties, which makes it 'obvious' that they are incompatible.
Thus, in that case I would argue for a `E_COMPILE_ERROR` instead of a notice.

The reason to use the stricter modifier is, well, arbitrary.

At least I do not find an argument for either way that completely convinces me.
At the moment, the main reason is that 'public' can be considered to be the default visibility modifier.
Based on the semantics of 'var' and dynamic properties.
Thus, private tends to imply that an additional constraint was consciously applied to the property, which should be preserved.
Well, but as I said, thats kind of arbitrary and if you look at the inheritance rules and try to reason from the view of clients with respect to the external interface, then going with public as the chosen modifier also starts to sound reasonable...


 


--TEST--
Conflicting properties with different visibility modifiers should be merged
to the most restrictive modifier.
--FILE--
<?php
error_reporting(E_ALL);

trait THello1 {
  public $hello = "foo";
}

trait THello2 {
  public $hello = "bar";
}

class TraitsTest {
	use THello1;
	use THello2;
	public function getHello() {
	    return $this->hello;
	}
}

$t = new TraitsTest;
?>
--EXPECTF--	
Fatal error: Conflicting definitions for property TraitsTest::$hello provided by THello1, THello2 in %s on line %d




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

---

## #51075 — Jonathan Bond-Caron — 2010-12-18T17:14:15+00:00

URL: https://externals.io/message/51007#51075 · In reply to: #51072

> At least I do not find an argument for either way that completely 
> convinces me.
> At the moment, the main reason is that 'public' can be considered to 
> be the default visibility modifier.
> Based on the semantics of 'var' and dynamic properties.
> Thus, private tends to imply that an additional constraint was 
> consciously applied to the property, which should be preserved.
> Well, but as I said, thats kind of arbitrary and if you look at the 
> inheritance rules and try to reason from the view of clients with 
> respect to the external interface, then going with public as the 
> chosen modifier also starts to sound reasonable...
> 

Does the order of the declaration matter?

trait THello1 {
  public $foo;
}

trait THello2 {
  private $foo;
}

trait THello3 {
  protected $foo;
}

class TraitsTest {
	use THello1;
	use THello2; // E_NOTICE: TraitTest conflict, THello2(private $foo)
ignored, already declared THello1(public $foo)
	use THello3; // E_NOTICE: TraitTest conflict, THello3(protected
$foo) ignored, already declared THello1(public $foo)
}

class TraitsTest2 {
	use THello3;
	use THello2; // E_NOTICE: ..
	use THello1; // E_NOTICE: ..
}

It could be that the first property 'wins' and an `E_NOTICE` is raised about
the property conflict.

Result:

class TraitsTest {
  public $foo;
}

class TraitsTest2 {
  protected $foo;
}

It would seem to fit php, though I'd be happy with simply E_FATAL until
people start using traits

The same for:

trait THelloA {
  public $foo = 'a';
}
trait THelloB {
  public $foo = 'b';
}
class TraitsTest3 {
  use THelloA;
  use THelloB; // E_NOTICE: TraitTest3 conflict, THelloB(public $foo)
ignored, already declared THelloA(public $foo)
}

class TraitsTest4 {
  use THelloB;
  use THelloA; // E_NOTICE: TraitTest3 conflict, THelloA(public $foo)
ignored, already declared THelloB(public $foo)
}

class TraitsTest5 {
  public $foo = 'c';

  use THelloB; // E_NOTICE: TraitTest3 conflict, THelloB(public $foo)
ignored, already declared TraitsTest5(public $foo)
  use THelloA; // E_NOTICE: TraitTest3 conflict, THelloA(public $foo)
ignored, already declared THelloB(public $foo)
}

---

## #51078 — Stefan Marr — 2010-12-18T17:33:48+00:00

URL: https://externals.io/message/51007#51078 · In reply to: #51075

Hi Jonathan:



> Does the order of the declaration matter?
No, the order does not matter, and that is one of the key points of traits compared to mixins or Python's way of multiple inheritance.
So, any kind of order-dependent solution would be inconsistent with the design of traits.

> though I'd be happy with simply E_FATAL until
> people start using traits
What do you mean by the second part? (until people start using traits)
Changing the design retrospectively does not seem to be the best option?

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

---

## #51080 — Jonathan Bond-Caron — 2010-12-18T19:08:18+00:00

URL: https://externals.io/message/51007#51080 · In reply to: #51078

> Hi Jonathan:
> 
> 
> 
> > […]
> No, the order does not matter, and that is one of the key points of 
> traits compared to mixins or Python's way of multiple inheritance.
> So, any kind of order-dependent solution would be inconsistent with 
> the design of traits.
> 
> > […]
> What do you mean by the second part? (until people start using traits) 
> Changing the design retrospectively does not seem to be the best 
> option?
> 

Most likely not the best option, I think I'm saying I prefer E_FATAL

But if users find it too restrictive / problematic, the auto-resolution
"merge to the most restrictive modifier" could be added in a next release or
an approach that's convenient to the code out there using traits &
properties. That seems better than the other way around.

---

## #51090 — Matthew Weier O'Phinney — 2010-12-19T16:22:38+00:00

URL: https://externals.io/message/51007#51090 · In reply to: #51072

> 
> > […]
> So, in general, I think, there is no 'right thing' to do here, because
> the definitions seem to be incompatible but that is only decidable at
> the application-level.
>
> There is another, related, edge-case in the test case below.  In the
> test we have different initial values for the properties, which makes
> it 'obvious' that they are incompatible.  Thus, in that case I would
> argue for a `E_COMPILE_ERROR` instead of a notice.
>
> The reason to use the stricter modifier is, well, arbitrary.
>
> At least I do not find an argument for either way that completely
> convinces me.  At the moment, the main reason is that 'public' can be
> considered to be the default visibility modifier.  Based on the
> semantics of 'var' and dynamic properties.  Thus, private tends to
> imply that an additional constraint was consciously applied to the
> property, which should be preserved.  

I'd argue that traits should follow similar rules to normal class
inheritance. In that paradigm, you can override a previously defined
member by using equal or _greater_ visibility only -- i.e., you can't
make it _less_ visible (e.g., making a property declared as protected in
the parent class private in the extending class). With traits, it seems
like we should go with whatever is _most_ visible, as then no matter
what traits are mixed in, access is guaranteed.

> Well, but as I said, thats kind of arbitrary and if you look at the
> inheritance rules and try to reason from the view of clients with
> respect to the external interface, then going with public as the
> chosen modifier also starts to sound reasonable...

Exactly. I wouldn't default to public on conflicts, though -- just with
the highest declared visibility (e.g., if one trait defines as private
and the other as protected, protected wins).

-- 
Matthew Weier O'Phinney
Project Lead            | matthew@zend.com
Zend Framework          | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc

---

## #51092 — Stefan Marr — 2010-12-19T19:04:11+00:00

URL: https://externals.io/message/51007#51092 · In reply to: #51090

Hi Matthew:


> Exactly. I wouldn't default to public on conflicts, though -- just with
> the highest declared visibility (e.g., if one trait defines as private
> and the other as protected, protected wins).
I am currently actually implementing the most restricted proposal: all differences in the property definition will lead to a fatal error.

The reasoning behind this is, that the semantics of state is not predictable and all changes in the class/traits hierarchies which are incompatible should give the developer an immediate feedback, i.e., make potentially incompatible code break.
That is not the most 'dynamic' of all possible solutions but seems to fit with the rest of PHP.

What I have in mind is also not how the methods integrate into the inheritance chain, thus, a property in the body of the class does not override all property definitions in traits (this is the case for methods).
I think that will be useful for the very same reason. And well, I hope an educative error message will steer the crowed in the right direction to use accessors.

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

---

Next page: https://externals.io/message/51007.md?page=2
