PHP - 静态与实例方法

Mak*_*kis 17 php oop

我有点困惑,因为我在PHP中没有太多的OOP经验.我总是听说使用实例方法比使用静态方法更好.为什么?

我需要一个深刻的答案和解释.

例如,为什么下面这个应该用实例方法完成?

控制器:

public function getProperty($id){
        $property = Property::getProperty($id);
        return $property;
}
Run Code Online (Sandbox Code Playgroud)

模型:

public static function getProperty($id){
        //$query = DB::table('properties')...
        //Some Code;
        return $query;         
}
Run Code Online (Sandbox Code Playgroud)

我正在阅读有关setter/getter,instance vs static等的内容.但我需要一个完整的答案来理解事物的方式原因.

Cra*_*tic 20

一般来说,正如您已经说过的,实例方法是更好的做法.这并不是说静态方法是彻头彻尾的邪恶,它们只是具有不同且独特的目的.

重要的是要注意,在处理实例方法时,您正在使用对象,而使用静态方法,您正在使用.使用静态方法时,您将无法访问通常可用于实例的任何非静态属性.

以下面的代码为例:

class Foo
{
    private $bar;
    private static $tavern;

    public function changeBar($value)
    {
        $this->bar = $value;
    }

    public function getBar()
    {
        return $this->bar;
    }

    public static function changeTavern($value)
    {
        self::$tavern = $value;
    }

    public static function getTavern()
    {
        return self::$tavern;
    }
}
Run Code Online (Sandbox Code Playgroud)

Class Foo具有静态属性$tavern和非静态属性$bar.

如果Foo创建了一个实例,则该对象可以使用所有属性和方法.

如果Foo以静态方式引用,则只有$tavern属性,changeTavern()方法和getTavern()方法可用于该类.

我们来看看以下代码:

$foo = new Foo();
$foo->changeBar('Tipsy Turvy');
echo $foo->getBar(); // prints Tipsy Turvy
Run Code Online (Sandbox Code Playgroud)

由于$foo是一个实例Foo,它可以访问整个类.通话changeBar()将修改该$bar属性.要$bar直接从静态方法更改属性,将触发错误,因为对象而不是$bar可用.

// Calling this method would trigger an error
public static function changeBar($value)
{
    $this->bar = $value; // PHP will crash and burn if you try this.
}
Run Code Online (Sandbox Code Playgroud)

如果要从静态方法访问类属性,则还必须将这些属性声明为static.这将在上面的类的上下文中工作.您还会注意到一个实例Foo读取静态属性没有问题.

Foo::changeTavern('Stumble Inn');
echo Foo::getTavern(); // prints Stumble Inn
echo $foo->getTavern(); // also prints Stumble Inn
Run Code Online (Sandbox Code Playgroud)

关于静态代码要记住的另一件事是它不像一个实例.当第一个实例Foo构建了两个属性$bar并且$tavern没有值时.如果您要创建另一个实例,Foo则会发现其中只有一个属性不再包含值.(我相信你现在可以猜到哪一个.)

$anotherFoo = new Foo();
echo $anotherFoo->getBar(); // prints nothing
echo $anotherFoo->getTavern(); // prints Stumble Inn
echo Foo::getTavern(); // prints Stumble Inn
Run Code Online (Sandbox Code Playgroud)

同样,静态代码意味着您直接使用 - 实例意味着您正在使用对象.重要的是要注意,您编写的任何类型的类都应该使用某种类型的状态作为实例.

静态类可能有点难以调试和测试.测试可能会有问题,因为在创建新实例时静态属性不会更改.调试也很困难,因为静态属性的值在类的所有实例中都是相同的.在一个中进行更改,您将在所有这些中进行更改.追踪哪个实例进行了更改是一件痛苦的事.

比喻说,使用像糖一样的静态类 - 只在必要时使用.

希望这有助于阐明这个话题.