php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #61943 Trait same property conflict in class extending
Submitted: 2012-05-04 20:07 UTC Modified: 2015-06-10 07:06 UTC
Votes:6
Avg. Score:4.0 ± 0.8
Reproduced:6 of 6 (100.0%)
Same Version:4 (66.7%)
Same OS:3 (50.0%)
From: franssen dot roland at gmail dot com Assigned: gron (profile)
Status: Closed Package: Scripting Engine problem
PHP Version: 5.4.2 OS: Ubuntu
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: franssen dot roland at gmail dot com
New email:
PHP Version: OS:

 

 [2012-05-04 20:07 UTC] franssen dot roland at gmail dot com
Description:
------------
Hi,

(version is actually 5.4RC9...)

The same property conflict happens when you have 2 traits (B uses A) where A defines the property, class Foo uses A and class Bar uses B _and_ extends Foo.

I would love to see the strict standard to be removed in this situation; how can a property have a conflict with itself?

Test script:
---------------
<?php
trait A {
    public $prop;
}
trait B {
    use A;
}
class Foo {
    use A;
}
class Bar extends Foo {
    use B;
}

Expected result:
----------------
<void>

Actual result:
--------------
Strict Standards: Foo and B define the same property ($prop) in the composition of Bar. This might be incompatible, to improve maintainability consider using accessor methods in traits instead.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-05-04 23:28 UTC] gron@php.net
-Assigned To: +Assigned To: gron
 [2012-05-04 23:28 UTC] gron@php.net
Hi:

From my point of view, it is not the same property.
My understanding is that you are moving here very much in the area of the typical diamond problem of 
multiple inheritance.

Theoretically, it is not clear whether the two properties should be handled as the same or not.

Why would you want to apply the trait a second time?

Best regards
Stefan
 [2012-05-05 09:00 UTC] franssen dot roland at gmail dot com
We can agree there's only 1 property definition right?

The concrete classes Foo and Bar will never define that property since that would be a "real" conflict.

So if you know that Bar::$prop is initially resolved from A::$prop as well as B::$prop you could say it's the same definition...

Why i want this? I want to extend a package in a subpackage on class level as well as trait level. The concrete subpackage classes extend the corresponding package classes and i don't want to override the package trait functions in each subpackage concrete class so the subpackage comes with its own trait, build upon the package trait.

It's really an architecture thing..

<?php
namespace Base {
    trait MainTrait { public $prop; }
    class Main { use MainTrait; }
}
namespace Base\Sub {
    trait MainTrait { use \Base\MainTrait; }
    class Main extends \Base\Main { use MainTrait; }
}
 [2012-05-05 09:12 UTC] gron@php.net
No, I disagree with your premise.

They are two different properties.
Look at the output of the following program.
This is a perfectly valid usecase and avoids name clashes.
Yes, the visibility is here private and it makes semantically a difference.

But still, defining a property with the same name in two classes in the same inheritance chain is always a code smell. And that is exactly what you are 
doing, since you got two 'use' declarations.

I can see your desire to make it logically one, but that does not fit into the 
idea of flattening a trait into a class.

<?php
error_reporting(E_ALL);

trait A {
    private $prop;
}
trait B {
    use A;
}
class FooT {
    use A;
}
class BarT extends FooT {
    use B;
}


class Foo             { private $prop; }
class Bar extends Foo {	private $prop; }
$o = new Bar;
var_dump($o);

$o = new BarT;
var_dump($o);
 [2012-05-05 09:35 UTC] franssen dot roland at gmail dot com
Of course.. private visibility.. you sir, are a genius :')

I get away with this since the trait is mainly for accessors only.

However, i have this (personal) convention to use protected properties with accessors, mainly pragmatic reasons (overriding default values by defintion). I think i'll need to revise my conventions for private properties usage, perhaps the strict way.

http://fabien.potencier.org/article/47/pragmatism-over-theory-protected-vs-private
 [2012-05-05 11:46 UTC] franssen dot roland at gmail dot com
I cheered to soon :-) now Bar has 2 individual property definitions (makes sense ofcourse), so this doesn't solve my architecture problem.

We can debat on if the architecture is a code smell or not, but i can understand i'm overusing traits here. Traits are simply not suitable for this.

I'll revise it so that the traits complement each other, rather than "extending" each other.
 [2012-05-05 11:50 UTC] franssen dot roland at gmail dot com
Also i did'nt read your comment well, especially the "semantical difference" part.. ;-)
 [2012-05-05 11:57 UTC] franssen dot roland at gmail dot com
E.g. something like;

<?php
trait A { }
trait B { }
class Foo { use A; }
class Bar extends Foo { use B; }
 [2015-06-09 14:18 UTC] cmb@php.net
-Status: Assigned +Status: Feedback
 [2015-06-09 14:18 UTC] cmb@php.net
So it seems this request can be closed?
 [2015-06-10 07:06 UTC] franssen dot roland at gmail dot com
-Status: Feedback +Status: Closed
 [2015-06-10 07:06 UTC] franssen dot roland at gmail dot com
Yes.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 19 15:01:28 2024 UTC