在PHP中使用类扩展特征?

Meg*_*lio 29 php oop traits

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

例如:

Trait T { }

Class C use T {}
/* or */
Class C extends T {}
Run Code Online (Sandbox Code Playgroud)

这种语法有没有潜在的冲突?我不这么认为.

mrl*_*lee 37

PHP手册如下:

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

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

要更直接地回答这个问题,你不要"扩展"一个特征,但你可以创建自己使用其他特征的特征.根据PHP手册:

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

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

trait HelloWorld {
    use Hello, World;
}

class MyHelloWorld {
    use HelloWorld;
}
Run Code Online (Sandbox Code Playgroud)

您可以将此视为一种在逻辑组中维护特征的方法,并引入一些模块化.

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

Parent > Trait > Child
Run Code Online (Sandbox Code Playgroud)

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


and*_*ber 20

你可以稍微扩展一下特征.扩展mrlee的答案,当你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
    }
}
Run Code Online (Sandbox Code Playgroud)

只需拉入父特征,将其replaceMe方法重命名为其他特征,并定义自己的replaceMe方法.

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
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在你的班上:

class MyClass {
    use MyTrait;
}
Run Code Online (Sandbox Code Playgroud)

现在这个类的对象可以这样做:

$obj = new MyClass();

$obj->keepMe();             // calls "parent" trait
$obj->replaceMe();          // calls "child" trait
$obj->frameworkReplaceMe(); // calls "parent" trait
Run Code Online (Sandbox Code Playgroud)


Joh*_*nde 6

只能扩展课程.特质不是课程.它们可以由类使用/包含,但不是类本身.如果你认为某个特征需要扩展,那么它可能应该是一个类,可能是一个抽象的,而不是一个特征.

  • 但是,如果我有一些第三方框架(Laravel,更确切地说)并且我需要它的一个特征,但是对于一个在特征中被标记为"受保护"的函数的小修复,该怎么办?我不想更改Laravel代码,所以有一些方法可以在我自己的特性中覆盖这个受保护的方法.更具体地说,问题在于我想要本地化的硬编码文本字符串. (4认同)
  • @Meglio:语法没有长度,因此没有更短的语法. (3认同)