4

我认为通常我们使用静态方法,因为我们不需要实例化对象。并且我们可以使用className::staticFunction调用静态方法,bub今天发现:

test1.php

<?php
class Foo { 
    static public function helloWorld() {
        print "Hello world " ;
    }
}
Foo::helloWorld();

test2.php

<?php
class Foo { 
    public function helloWorld() {
        print "Hello world " ;
    }
}
Foo::helloWorld();

问题:

以上两个脚本都有效。我们没有将函数声明为static,我们仍然可以使用className::staticFunction来调用函数。为什么我们需要使用静态方法?

4

6 回答 6

5

我们没有将函数声明为静态的,我们仍然可以使用className::staticFunction

您可能没有注意到 PHP 抱怨第二种调用类型:

Foo::helloWorld()PHP 严格标准:不应该在第 1 行的 php shell 代码中静态调用非静态方法

严格标准:非静态方法Foo::helloWorld()不应在第 1 行的 php shell 代码中静态调用

要使这些通知可见,您需要使用或通过配置文件将 的值设置error_reporting为;顺便说一句,在开发过程中建议这样做。-1ini_set()php.ini

结论

静态调用的函数应声明为static function xyz().

更新

顺便说一句,使用范围解析运算符::并不一定意味着您正在进行静态调用;考虑这个例子:

class Foo 
{ 
    public function helloWorld() 
    {
        print "Hello world ";
    }

    public function doSomething()
    {
        self::helloWorld();
    }
}

$f = new Foo;
$f->doSomething();

这是有效的,因为 usingself::而不是Foo::不会更改调用“模式”(除非您调用的方法定义为static)。

于 2013-08-16T06:52:29.980 回答
2

静态方法的“问题”是它们的调用方式:

Foo::bar();

对静态方法的任何调用都必然是硬编码的,并且不能轻易被替换。与之比较:

$foo->bar();

$foo在这里是一个变量,意味着bar()可以替换的确切对象和实现。这对于依赖注入很重要,也是依赖注入的基础。

您将使用静态方法:

  • 首先是不需要单个对象实例的情况
  • 在实例化对象之前您需要做的任何事情
  • 替代对象构造函数,例如,DateTime::createFromFormat()而不是new DateTime
  • 您 100% 确定永远不需要替换或模拟的幂等实用程序函数

可以在其他场景中到处使用静态函数,但这些是要点。您需要注意,将方法声明为静态意味着您需要静态调用它,这意味着它的调用时使用不能真正改变。有关此主题的长篇条约,请阅读如何不使用静力学破坏您的可测试性

于 2013-08-16T07:01:46.097 回答
0

PHP 就是这样有趣,但我通常会有一个实用程序类,它接受事物的参数来执行逻辑并返回。像这样的东西不需要实例化的类。正确调用方法取决于用户/开发人员(阅读:使用正确的方法访问器)。

于 2013-08-16T06:35:17.497 回答
0

当您处理基于 OOP 的大型项目时,您无疑会使用许多类(父类和子类)。这样做的一个不幸结果是,为了访问来自不同类的元素,必须手动将它们传递给每个类(或者更糟的是,将实例存储在全局变量中)。这可能会非常令人沮丧,并可能导致代码混乱和整体糟糕的项目设计。值得庆幸的是,静态元素可以从任何上下文(即脚本中的任何位置)访问,因此您可以访问这些方法,而无需在对象之间传递类的实例。

由于您不需要声明对象实例来访问静态元素,因此可以避免不必要的声明来访问看似简单的函数。

静态元素在类的每个实例中都可用,因此您可以设置希望对类型的所有成员可用的值。

于 2013-08-16T06:38:55.593 回答
0

从上面的例子test1.php

helloworld()由于您添加了静态关键字,因此无法覆盖重载函数。

然而在第二个例子中,test2.php

helloworld()函数可以重载覆盖

插图:1(作品)

<?php
class Foo {
    function helloWorld() {
        print "Hello world " ;
    }
}

class Foo1 extends Foo
{
    function helloWorld()
    {
        echo "Foo's World";
    }
}
$Foo1 = new Foo1();
$Foo1->helloWorld(); //Foo's World

插图:2(失败)

不能使静态方法 Foo::helloWorld() 非静态

<?php
class Foo {
    static function helloWorld() {
        print "Hello world " ;
    }
}

class Foo1 extends Foo
{
    function helloWorld()
    {
        echo "Foo's World";
    }
}
$Foo1 = new Foo1();
$Foo1->helloWorld();
于 2013-08-16T06:28:31.767 回答
0

好吧,一个简单的 hello world 程序可能无法显示出很大的区别,那就是 static 与 not 的用法,但看看这个类

class foo {


    private $a = 1;

    private static $b = 2;


    public function foobar()
    {
        echo $this->a;
    }

}

在上面的这个类中,如果你foobar静态调用,那么$this->a将无法解决。

于 2013-08-16T06:28:36.550 回答