Php 侦听静态父方法的子类

Php 侦听静态父方法的子类,php,static-methods,Php,Static Methods,我很确定我的问题已经在某个地方得到了回答,但似乎我找不到答案,所以我在这里尝试 子类是否有办法侦听其父类的静态方法并执行其静态方法之一?或者它应该使用一个接口,如果是,你会怎么做 最好的例子是命令类:您有: class Command { public static function execute($name, $args) { // Do something } } 当您调用该方法execute时,所有子类都会查看名称是否对应于它们的名称 class Sub

我很确定我的问题已经在某个地方得到了回答,但似乎我找不到答案,所以我在这里尝试

子类是否有办法侦听其父类的静态方法并执行其静态方法之一?或者它应该使用一个接口,如果是,你会怎么做

最好的例子是命令类:您有:

class Command {
    public static function execute($name, $args) {
        // Do something
    }
}
当您调用该方法execute时,所有子类都会查看名称是否对应于它们的名称

class Subcommand extends Command {
    public static $name = "command";

    public static function execute($name, $args) {
        if (self::$name === $name) {
            // Do something
        }
    }
}
问题是必须有多个类,比如Subcommand,我不想手动调用所有这些类,应该有自动调用的方法

现在,我在命令类中放置了一个数组,如下所示:

$commands = [
    Subcommand1::class,
    Subcommand2::class,
    Subcommand3::class
    // …
]

我迭代它并调用每个子类的execute方法,但我希望能有更优雅的方法来实现这一点。

实际上,我认为您当前的方法是优雅的(看看设计模式)


据我所知,您试图实现的是执行
命令
的所有注册子类的方法。这至少有两点不优雅首先,您必须从所有声明的类中筛选出子类(使用)。这可能是非常详尽的其次,在这种情况下,您只能通过添加或删除类来控制要执行的命令数。这实际上违背了面向对象编程(面向对象编程,而不是面向类编程)的目的。程序的流程应该由对象的交互来定义。

执行()的
$name
参数感觉需要在这里检查:

  • 它的有效值是什么?(它是完全自由形式的,还是从某个枚举中选择的?)
  • 它们与子命令的关系如何?(1对1?1对多?多对多?)
  • 打电话的人是如何选择的
我很想说,
execute()
的调用方不应该传递这些信息;如果它知道使用哪个命令,它应该构造一个表示该命令的对象

如果每个名称与一个子命令一一对应,那么调用方只需实例化子命令类即可。如果是一对多或多对多关系,则需要一些额外的“命令类型”类;或者,您可以每次构造相同的对象,但使用它应该分派到的子命令列表

您可能还需要一个工厂方法,该方法以命令的名称命名,并构造适当的子命令或命令类型。这允许命令的选择是动态的,例如从用户输入,并保持任何复杂的逻辑,关于在一个地方创建什么对象。这可能是一个硬编码的switch语句,您可以在其中管理所有名称到类的关系,也可能是一个注册表,新的子类可以在其中注册特定的命令名


最后一种情况本质上是观察者模式:命令名是事件,子类已注册以观察它们。正如
sevavietl
那样,这使得关系更加明确:如果某个类实际上没有在任何地方列出,那么该类的存在通常不会触发行为。在PHP中尤其如此,在PHP中,类通常只在第一次引用时在磁盘上查找,所以在运行时您实际上不知道项目包含多少类。

当您说“子类”时,您是指子类吗?比如,一个扩展类?我不&39;我不知道英文名字哈哈,当你使用extends时,是的,这没关系,只是想澄清你的问题。你能举一些你想达到的目标的例子并解释一下你有什么问题吗?我编辑了这篇文章,它更好吗?我明白了,谢谢你的回答,它很清楚。那么我将使用我目前的方法,$name完全是自由形式的,子类只需检查它是否与它们的名称对应,然后根据这一点执行它们自己。我希望这样做,以避免在我有20-30个不同命令的情况下使用20-30个if语句。我想我会再看一遍你的信息,因为它有很多有用的信息,如果它最后变成“我不应该这样做”,我会考虑所有其他的方法来做到这一点。谢谢你花时间回答我!:D@Coq对我来说,这听起来很像一个观察者模式,
$name
的值是任意事件,类为特定事件注册自己。然后,您只需在事件到观察者的关联数组中维护映射,例如,
['foo'=>[$instanceOfFooHandler,$InstanceOfferythinghHandler],'bar'=>[$InstanceOffBarHander,$InstanceOfferythinghHandler]
。这样,您就不需要任何if语句,而您循环遍历所有子类的唯一时间是在某种引导代码中为事件注册它们时。