使用PHP中的类扩展特征?

2022-08-30 12:52:31

为什么我们不允许在PHP中使用类扩展Traits?

例如:

Trait T { }

Class C use T {}
/* or */
Class C extends T {}

这种语法是否存在任何潜在的冲突?我不这么认为。


答案 1

PHP手册指出:

Traits 是一种在单继承语言(如 PHP)中重用代码的机制。Trait 旨在通过使开发人员能够在位于不同类层次结构中的多个独立类中自由重用方法集来减少单继承的某些限制。Traits 和类组合的语义以一种降低复杂性的方式定义,并避免了与多重继承和 Mixins 相关的典型问题。

如果你想扩展一个特质,那么它可能应该是一个类。如果你在一个类中有一组方法,你想在其他类中使用,但扩展类(例如)感觉不合适,那么在PHP 5.4中,它可以很好地作为一个特征。class Animal extends Vehicle

为了更直接地回答这个问题,你不会“扩展”一个特质,但你可以创造一个本身使用其他特质的特质。根据 PHP 手册:

trait Hello {
    public function sayHello() {
        echo 'Hello ';
    }
}

trait World {
    public function sayWorld() {
        echo 'World!';
    }
}

trait HelloWorld {
    use Hello, World;
}

class MyHelloWorld {
    use HelloWorld;
}

您可以认为这是在逻辑组中维护特征并引入一些模块化的一种方式。

编辑:看过一些评论后,我认为值得注意的是,在基类中使用特征也意味着该特征位于扩展它的任何类中,并且特征的功能优先于基类。将其放在子类中只会使父类/基类无法使用特征的函数。

Parent > Trait > Child

http://php.net/manual/en/language.oop5.traits.php


答案 2

你可以在某种程度上扩展特征。扩展mrle的答案,当你有一个特质时,你可以重命名它的方法。use

例如,假设您有一个由您的框架定义的“父”特征:

trait FrameworkTrait {
    public function keepMe() {
        // Framework's logic that you want to keep
    }

    public function replaceMe() {
        // Framework's logic that you need to overwrite
    }
}

只需提取父特征,将其方法重命名为其他名称,然后定义自己的方法即可。replaceMereplaceMe

trait MyTrait {
    use FrameworkTrait {
        FrameworkTrait::replaceMe as frameworkReplaceMe;
    }

    public function replaceMe() {
        // You can even call the "parent" method if you'd like:
        $this->frameworkReplaceMe();

        // Your logic here
    }
}

然后在你的课堂上:

class MyClass {
    use MyTrait;
}

现在,此类的对象可以执行以下操作:

$obj = new MyClass();
    
$obj->keepMe();             // calls "parent" trait
$obj->replaceMe();          // calls "child" trait
$obj->frameworkReplaceMe(); // calls "parent" trait

推荐