你什么时候需要使用后期静态绑定?

rg8*_*g88 9 php oop

在阅读了后期静态绑定(LSB)的描述后,我非常清楚地看到了发生了什么.现在,哪种情况最有用或最需要?

Ale*_*ein 6

我在以下场景中需要LSB:

  • 想象一下,您正在构建一个"邮件处理器"守护程序,它从电子邮件服务器下载邮件,对邮件进行分类,解析,保存,然后执行某些操作,具体取决于邮件的类型.
  • 类层次结构:您有一个基类Message类,其子项为"BouncedMessage"和"AcceptedMessage".
  • 每种消息类型都有自己的方式在磁盘上保留自己.例如,BouncedMessage类型的所有消息都尝试将自身保存为BouncedMessage-id.xml.另一方面,AcceptedMessage需要以不同的方式保存自己 - 作为AcceptedMessage-timestamp.xml.这里重要的是确定文件名模式的逻辑对于不同的子类是不同的,但是对于子类中的所有项共享.这就是为什么它在静态方法中才有意义.
  • Base Message类有一个抽象的静态方法(yes,abstract AND static)"save".BouncedMessage使用具体的静态方法实现此方法.然后,在实际检索消息的类中,您可以调用":: save()"

如果您想了解有关该主题的更多信息:

  • 如果您可以在这种情况下添加*为什么*,那么使用 ```static::`` 会比简单地使用抽象的、*非静态* 方法更好或更容易,这将很有帮助。对我来说,似乎 ```save()``` 是你没有理由从静态上下文中调用的东西,但也许我错过了一些东西。 (2认同)

Ada*_*nco 5

我对后期静态绑定的一个主要需求是一组静态实例创建方法.

这个DateAndTime类是我从Smalltalk/Squeak移植到PHP的时间库的一部分.使用静态实例创建方法可以创建具有各种参数类型的实例,同时在静态方法中保留参数检查,以便库的使用者无法获取不完全有效的实例.

在这种情况下,后期静态绑定非常有用,因此这些静态实例创建方法的实现可以确定调用最初所针对的类.以下是一个用法示例:

使用LSB:

class DateAndTime {

    public static function now() {
        $class = static::myClass();
        $obj = new $class;
        $obj->setSeconds(time());
        return $obj;
    }

    public static function yesterday() {
        $class = static::myClass();
        $obj = new $class;
        $obj->setSeconds(time() - 86400);
        return $obj;
    }

    protected static function myClass () {
        return 'DateAndTime';
    }
}

class Timestamp extends DateAndTime {

    protected static function myClass () {
        return 'Timestamp';
    }
}


// Usage:
$date = DateAndTime::now();
$timestamp = Timestamp::now();

$date2 = DateAndTime::yesterday();
$timestamp2 = Timestamp::yesterday();
Run Code Online (Sandbox Code Playgroud)

如果没有后期静态绑定,[在我当前的实现中]每个类必须实现每个实例创建方法,如下例所示:

没有LSB:

class DateAndTime {

    public static function now($class = 'DateAndTime') {
        $obj = new $class;
        $obj->setSeconds(time());
        return $obj;
    }

    public static function yesterday($class = 'DateAndTime') {
        $obj = new $class;
        $obj->setSeconds(time() - 86400);
        return $obj;
    }

}

class Timestamp extends DateAndTime {

    public static function now($class = 'Timestamp') {
        return self::now($class);
    }

     public static function yesterday($class = 'Timestamp') {
        return self::yesterday($class);
    }

}
Run Code Online (Sandbox Code Playgroud)

随着实例创建方法和类层次结构的数量增加,方法的重复变成了对接中的真正痛苦.LSB减少了这种重复,并允许更清晰,更直接的实现.