Traits – Method Precedence and Conflict resolution

In our previous post about the multiple and nested traits, we read how nested and multiple traits can be used in a class. In such cases, there is a possibility of the same method name existing in the trait, and the class using the trait. Furthermore, the same method name might also be present in the parent class of the class using traits. It is important to understand how the precedence order works for such cases.

Method Precedence

There are different scenarios of the method name conflict. We will read about the different cases.

Class Method Overrides Trait Method

A class name gets higher precedence over a trait method. So, the class method will get executed.

trait imTrait {

public function method1() {

echo 'I am in the Trait Method!';

}

}

class imClass {

use imTrait;

public function method1() {

echo 'I am in the class Method!';

}

}

// create class object

$obj = new imClass();

$obj->method1(); //Outputs: I am in the class Method!

This, the class method overrides the trait method.

Trait Method Overrides an Inherited Method

Class method gets higher precedence over Trait method. But, a trait method will override an inherited method.

trait imTrait {

public function method1() {

echo 'I am in the Trait Method!';

}

}

class base {

public function method1() {

echo 'I am in the base class Method!';

}

}

class imClass extends base {

use imTrait;

}

// create class object

$obj = new imClass();

$obj->method1(); //Outputs: I am in the Trait Method!

The code snippets are basic usage example and are just for illustration purposes.

Precedence Order for Trait methods

Above cases can be clearly defined and are very simple. However, the traits have equal precedence. When we are using two traits and both contain overlapping method names, then they get equal precedence. By default, this situation gives a fatal error. To handle such cases, PHP provides two operators:

  1. insteadof operator: This method chooses one of the two conflicting methods
  2. as operator: This operator allows us to use one of the two conflicting methods with a different name.

How to Use insteadof Operator?

Two traits can have methods with same name. When both traits are being used by same class, this will result in a conflict and produce a fatal error. The insteadof operator resolves this error when we intend to use only one of the two conflicting methods.

trait trait1 {

public function traitMethod1() {

echo 'I am in method1 of trait1!';

}

}

trait trait2 {

public function traitMethod1() {

echo 'I am in method1 of trait2!';

}

}

class class1 {

use trait1, trait2

{

trait1::traitMethod1 insteadof trait2;

// Above statement tells the class to use the traitMethod1 of trait1 only

}

}

$obj = new class1();

$obj->traitMethod1();// Outputs: I am in method1 of trait1!

How to Use as operator?

There can be a case where the implementation of the conflicting methods is such that you need to add both methods to the class. In such a case, insteadof operator won’t solve the purpose. PHP provides the as operator for such scenarios.

trait trait1 {

public function traitMethod1() {

echo 'I am in method1 of trait1!';

}

}

trait trait2 {

public function traitMethod1() {

echo 'I am in method1 of trait2!';

}

}

class class1 {

use trait1, trait2

{

trait1::traitMethod1 insteadof trait2;

// Above statement tells the class to use the traitMethod1 of trait1 only

trait2::traitMethod1 as traitMethod2;

// Above statement tells the class to use the traitMethod1 of trait2 as traitMethod2

}

}

$obj = new class1();

$obj->traitMethod1();// Outputs: I am in method1 of trait1!

$obj->traitMethod2();// Outputs: I am in method1 of trait2! 

The as operator provides an alias name for the one of the conflicting methods. The method is not renamed but can be invoked by this alternate name.

2 Responses to “Traits – Method Precedence and Conflict resolution”

  1. Please be cognizant of the fact that traits are largely a crutch for those who have not mastered the more helpful Design Patterns (hint: STRATEGY PATTERN!).

    An author on StackOverflow says it best: “Often traits are used as a crutch for poor design when unique class implementations would suffice. You should limit traits to fulfilling interface requirements for best code design.” http://stackoverflow.com/a/9205347

    Reply
    • refulz

      Well Traits is a new addition to PHP, with an aim to increase code reusability in a language that doesnt support multiple inheritance. Without over doing and using it just for the sake of using traits, it can help in increasing code re-usability.
      I agree with the remark, but the same author on Stackoverflow also tells about scenarios where traits can be used.
      Quoting: “You should only use traits when multiple classes share the same functionality (likely dictated by the same interface). There’s no sense in using a trait to provide functionality for a single class”.
      Thanks for visiting the blog and sharing your views. The different views help readers understand different perspectives.

      Reply

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>