Using Interface to make a Class Trait-compatible

Jahanzeb Khan

Is it OK (good practice OOP wise) to make a class implement a certain interface so that a trait being used in that class can access the classes functions.

I found a SO question a few days ago with an answer explaining that traits shouldn't use methods/things from the class it's being used in. What If I made a class implement an interface so it had to have those functions that the trait uses from the class? Would that be OK. I'm taking an OOP class in university next year, so I only learned what OOP I did from the internet, in case this is a bad question. :p

So here's the idea to clarify (in PHP)

trait MyTrait {
  public function foo() {
    return $this->bar(); // bar is in the class the trait is to be used in
  }
}

class MyClass implements MyTraitCompatible {
  public function bar() {
    return "BAR!";
  }
}

interface MyTraitCompatible {
  public function bar();
}

Also, is there anyway to enforce that a class needs to implement MyTraitCompatible to use MyTrait?

Edit: (My actual goal is to have one function used in two classes that both extend another class (Eloquent) and would be completely identical but the function would not be used in all classes extending Eloquent - this is one way I thought of doing it.)

Robbie Averill

One option is that your trait could check that the class using it implements the interface you expect. Here's an example in the constructor method:

trait MyTrait {
    public function __construct() {
        if (!in_array('MyTraitCompatible', class_implements($this, false))) {
            throw new Exception('To use this trait you must implement MyTraitCompatible!');
        }  
    }

    public function foo() {
        return $this->bar(); // bar is in the class the trait is to be used in
    }
}

A valid class would be:

class MyClass implements MyTraitCompatible {
    use MyTrait;
    public function bar() {
        return "BAR!";
    }
}

An invalid class would be:

class InvalidClass {
    use MyTrait;
    public function baz() {
        return "I don't think so buddy.";
    }
}

Obviously if the class using this trait has a constructor already then this would conflict. There isn't a pretty way to avoid this since the class using the trait will have precedence over the trait and would just override it. One option is that you could define a check method in the trait and call it from the methods in the trait to check compatibility, but it's not ideal:

trait MyTrait {
    protected function compatible() {
        if (!in_array('MyTraitCompatible', class_implements($this, false))) {
            throw new Exception('To use this trait you must implement MyTraitCompatible!');
        }
        var_dump('Passed the test!');
    }

    public function foo() {
        $this->compatible();
        return $this->bar(); // bar is in the class the trait is to be used in
    }
}

You could also replace that compatible() method with the __call() magic method - but again, you might run into conflicts if you have one defined elsewhere.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Declaration of class must be compatible with interface

From Dev

How to make interface compatible on different screen resolution

From Dev

PHPUnit with abstract class using trait

From Dev

Make Class Library compatible to DNX Core 5

From Dev

Using a class that implements an interface

From Dev

If a class is using an interface, it must

From Dev

using base class in interface

From Dev

Using : on a class and interface

From Dev

If a class is using an interface, it must

From Dev

Using Interface and Abstract class

From Dev

How do I make my custom class compatible with For Each?

From Dev

using a class to make an object

From Dev

Using a method declared in an interface, but not class

From Dev

How to make an interface class out of ApplicationDbContext?

From Dev

Groovy make a class implement an interface via metaprogramming

From Dev

Using an interface class as member type in another class

From Dev

How to make different objects compatible with IPhone and IPad using Spritekit

From Dev

Error "return type int is not compatible with Intent" when using FirebaseMessagingService class

From Dev

php trait using another trait

From Dev

php trait using another trait

From Dev

Using Macro to Make Case Class

From Dev

Case class implementing trait

From Dev

Trait that counts instances of class

From Dev

Use trait as interface for database entity

From Dev

Using interface to export class from dll

From Dev

Mocking a class with an explicitly implemented interface using Foq

From Dev

TypeScript: Reference interface in class when using AMD

From Dev

using reflection to get properties of class inheriting an interface

From Dev

Anonymous inner class using an interface in Java

Related Related

HotTag

Archive