在PHP中为traits使用final关键字

3
我希望能够创建"最终特征",并具有以下行为。我意识到这不可能通过traits实现(或者可以吗?那会让我非常高兴),但我只是想传达我的意图。
因此,我希望拥有一个特征,它应该:
trait Content {
    public final function getPostContent(){ /*...*/ }
    public final function setPostContent($content){ /*...*/ }
}

我需要的是:

将特征中的函数标记为final,确保如果一个类使用了这个特征,那么特征实现就是被保证的实现。

class MyClass {
    use Content;
    public function getPostContent() { // This should not be allowed
        return null;
    }
}

我希望能够以某种方式检查类是否使用了一个 traits(例如, $myObject instanceof Content)的方法。
class MyClass {}
class MyClassWithContent {
    use Content;
}
var_dump((new MyClass) instanceof Content); // "bool(false)"
var_dump((new MyClassWithContent) instanceof Content; // "bool(true)"

确保在使用trait时,不能更改方法的名称/可见性。因此,不应允许出现这种情况。
class MyDeceptiveClass {
    use Content {
        Content::getPostContent as nowItsNotCalledGetPostContentAnymore();
        Content::setPostContent as protected; // And now setPostContent is protected
    }
}

2
古老的问题:我如何防止可以访问源代码的人做我不想要的事情?简短的答案是“你不能”,你必须学会接受这一点。在“类型提示”特征方面,更好的选择是使用特征实现的接口。 - samlev
当然,在许多情况下你可以这样做。例如,我认为这是强类型语言的优势之一,也是良好类设计的结果。不过还是谢谢你,我不知道traits可以实现接口。 - SomeNorwegianGuy
另外需要注意的是:Python(作为一个例子)没有“公共”和“私有”的概念,因为它作为一种语言,认为如果人们可以扩展你的代码,他们就可以替换/修改/更新你的代码。我认为这些关键字更多的是提示性的,而不是实际上的限制性的。它们对于确定程序流程很有帮助,但对于防止欺诈行为并不是很有帮助。 - samlev
抱歉,为了澄清“trait/interface”这个问题,trait不能直接实现interfaces(我希望它们可以),但你可以说类实现了interface,并在类中使用trait。请参见此pastebin - samlev
显示剩余3条评论
1个回答

4

在特质中定义的方法会被类中定义的方法覆盖,即使特质方法被声明为final

<?php
trait Bar {
    final public function fizz() {
        echo "buzz\n";
    }
}

class Baz {
    use Bar;

    public function fizz() {
        echo "bam\n";
    }
}

$x = new Baz;
$x->fizz(); // bam

查看Traits文档中的优先级部分

来自基类的继承成员会被Trait插入的成员覆盖。优先级顺序是当前类的成员覆盖Trait方法,而Trait方法又覆盖继承方法。


这样做违背了在 trait 中定义方法为 final 的初衷。 - Jay Bienvenu
不完全是。Traits 不是继承,它们更像是 Mixin。在 Trait 中,你并没有重新定义一个方法,而是不使用 Trait 中的方法(因为它已经在你的类中定义过了)。Traits 有点像继承的唯一情况是属性定义。Trait 和使用该 Trait 的类中不能有不同的属性定义(例如,如果 Trait 定义了 public string $foo = 'bar';,那么你的类就不能定义 public string $foo = 'baz'; 或者修改 $foo 的定义)——不要问我为什么。 - samlev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接