静态方法:考虑到PHP 5.3后期静态绑定,它们仍然不好吗?

dyn*_*mic 11 php oop singleton design-patterns dependency-injection

如果你搜索静态方法不好的原因,你发现它的第一件事是因为你在单元测试时不能覆盖它.

因此,考虑到PHP 5.3,你可以通过引入做任何你想做的事情static::吗?

加:

http://sebastian-bergmann.de/archives/883-Stubbing-and-Mocking-Static-Methods.html

注意他甚至解释了如何使用单例而没有任何测试问题:

Lig*_*ica 12

如果你有一个静态成员函数,它通常可以是一个自由函数.通常的反应是编码器选择静态成员函数只是因为"一切都必须在一个对象中"的神话.

这就是人们劝阻他们的原因.

并且,因为这不是一个非常有说服力的论点,那些人指的是单元测试.不知道他们现在会做什么.

  • @ yes123:在这一点上,我们首先会问你为什么要有一个课程.(实际的答案当然是,PHP的命名空间语法是新的和可怕的......但这不是真正的重点.) (3认同)
  • @ yes123 Logger应该是您实现的接口(例如FlatFileLogger). (3认同)

Lot*_*tes 10

静态方法本身并不坏.有时某些操作对于要求特定对象没有意义.例如,像平方根这样的函数更有意义是静态的.

Math::sqrRoot(5);
Run Code Online (Sandbox Code Playgroud)

而不是必须实例化一个Math'对象',然后调用该函数.

$math = new Math();
$result = $math->sqrRoot(5);
Run Code Online (Sandbox Code Playgroud)


koe*_*oen 6

更难测试是一个原因,但不是唯一的原因.静态方法提供全局访问,而全局访问则很糟糕.

当然,你会发现对象有另一个全局访问权限,而且正在用'new'创建一个对象.必须在某处创建对象,因此我们无法消除它(尽管最小化它是一个好主意).作为对类的全局访问的静态方法很糟糕,除非通过更高级别的编程替换"new":

$user = new User();
$user->setPointsTo(100);

// vs

$user = User::with100StartingPoints();
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我创建的代码更易读,同时不会滥用全局访问(无论如何都需要调用'new').

编辑:让我举一个例子,静态方法'可以'是可测试性的死亡(请注意上面的例子中你甚至不需要模拟静态方法但可以轻松测试新的静态方法产生的同样的结果).让我们使用您的记录器示例:

class Logger {
    public static function log($text) { // etc }
}

class AccessControl {
    public function isAllowed(User $user, $action) {
      // do stuff, determine if $allowed
      if (!$allowed) {
          Logger::log('user X was not allowed to do Y');
      }
      // do stuff
    }
}
Run Code Online (Sandbox Code Playgroud)

由于对Logger :: log的全局调用,我们无法干净地测试此方法.这将取决于Logger类的正确工作.