Multi-inheritance is realized by using trait, but the type of parameters cannot be limited. For example, the following example
trait T{
function t(){
echo 'trait';
}
// Omit many other codes
}
class B{ } // Assume that B is a third-party module
class C extends B{ // Assume that C must inherit the module B
use T;
}
// Some functions in some classes in the following client code may need to use several methods in T, like the following.
function f(T $t){ // Type-hinting for the trait T, but there is a problem
$t->t();
}
f(new C);
Sandbox test found an error Fatal error: Uncaught TypeError: f(): Argument #1 ($t) must be of type T, C given
If f(T $t) is changed to f(C $t) or f($t), it will be fine, but this is not what I want.
It won't work if the trait is changed to an interface, because the function body can't be written in the interface.
It won't work if the trait is changed to a class, because C has already inherited one class and can't inherit another.
What can we do to realize multi-inheritance and restrict types?
I have an idea. I wonder if it can be realized. That is to say, write a module specially designed to handle the exception of trait type, and then include the module globally at the beginning of my project. The logic of the module is roughly as follows:
- Match the keywords T and C in the exception message
must be of type T, C given; - Use the ReflectionClass to get the code block of C;
- Search for the keyword
use Tin the code block of C. If found, ignore the exception and continue to execute the code, otherwise, throw the exception.
We can use set_exception_handler('exception _ handler') to catch exceptions. The question is how to ignore this exception and ensure that the program continues to execute?