在静态函数内访问公共/私有函数?

8
由于在静态函数中无法使用$this->,那么你该如何访问静态函数以外的普通函数呢?
private function hey()
{
    return 'hello';
}

public final static function get()
{
    return $this->hey();
}

这会抛出一个错误,因为你不能在静态方法中使用 $this->。

private function hey()
{
    return 'hello';
}

public final static function get()
{
    return self::hey();
}

这会抛出以下错误:
Non-static method Vote::get() should not be called statically

如何在静态方法中访问同一类中的常规方法?*


如果你想调用那些没有访问$this的函数,你必须将它们改为静态函数。 - user142162
将类引用传递给你的静态方法。 - Mike Corcoran
我应该如何处理这个?例如在hey()函数中,使用return $this->get("hello") - Jony Kale
抱歉,但是...你真的理解静态和面向对象编程吗?请别误会。 - coma
你不能这样做。静态方法是在类范围内操作的,你无法访问实例方法,因为你必须实例化该类的对象(例如单例模式)。 - Ivan Fateev
3个回答

9

静态方法只能调用类中的其他静态方法。如果您想访问非静态成员,则该方法本身必须是非静态的。

或者,您可以将对象实例传递到静态方法中并访问其成员。由于静态方法在与您感兴趣的静态成员相同的类中声明,因此由于PHP中的可见性工作方式,它仍然可以正常工作。

class Foo {

    private function bar () {
        return get_class ($this);
    }

    static public function baz (Foo $quux) {
        return $quux -> bar ();
    }
}

但请注意,仅因为您可以这样做,并不意味着您应该这样做。这种代码会破坏良好的面向对象编程实践。


实际上,这是工厂模式中非常有效的一种模式。这也是一种构造函数重载的方式... 从某种意义上讲,它是与各种初始化函数相结合的工厂模式。 - Nux

7
您可以将实例的引用提供给静态方法:
class My {
    protected myProtected() {
        // do something
    }

    public myPublic() {
        // do something
    }

    public static myStatic(My $obj) {
        $obj->myProtected(); // can access protected/private members
        $obj->myPublic();
    }

}

$something = new My;

// A static method call:
My::myStatic($something);

// A member function call:
$something->myPublic();

如上所示,静态方法可以访问它们所属类的对象的私有和受保护成员(属性和方法)。

或者,您可以使用单例模式评估此选项),如果您只需要一个实例。


0

我通过在静态方法中创建一个相关类的对象来解决这个问题。这样,我可以将一些特定的公共函数作为静态函数公开。其他公共函数只能像$object->public_function();这样使用。

以下是一个小代码示例:

class Person
{
  public static function sayHi()
  {
    return (new Person())->saySomething("hi");
  }

  public function saySomething($text)
  {
    echo($text);
  }

  private function smile()
  {
    # dome some smile logic
  }
}

这种方式只能使用静态函数说“hi”,但是在创建对象时也可以说其他的话,例如$peter->saySomething('hi');。 公共函数也可以使用这种方式调用私有函数。

请注意,我不确定这是否是最佳实践,但在我想要能够生成令牌而不必每次手动创建对象的情况下,它可以正常工作。

例如,我可以简单地发出或验证令牌字符串,如TokenManager::getTokenToken();TokenManager::verifyToken("TokenHere");,但我也可以发出一个令牌对象,如$manager = new TokenGenerator();,以便我可以使用功能,如$manager->createToken();$manager->updateToken(updateObjectHere);$manager->storeToken();


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接