为什么PHP中使用的对象上下文的静态方法?(Why PHP uses static methods

2019-07-18 08:56发布

我有以下代码(如,真的,这是我真正的代码):

<?php
class Foobar
{
  public static function foo()
  {
    exit('foo');
  }
}

当我运行$foobar = new FooBar; $foobar->foo() $foobar = new FooBar; $foobar->foo()它显示foo

为什么PHP会在对象上下文中使用一个静态方法? 是否有办法避免这种情况?


好吧,你们没得到我的问题:我知道静态和非静态方法和如何调用它们之间的差异。 这是我的整点,如果我叫$foobar->foo()为什么PHP试图运行一个静态方法?


注:我运行PHP 5.4.4,错误报告E_ALL

Answer 1:

要调用一个静态方法,您不使用:

$foobar = new FooBar;
$foobar->foo()

你叫

FooBar::foo();

PHP手册说...

声明类属性或方法为静态,使他们无需类的实例访问。 声明为静态属性不能与实例化的类对象(尽管一个静态方法可以)进行访问。

这就是为什么你可以致电实例的方法,尽管这是不是你打算做。

无论你是否调用静态方法静态或实例,您无法访问$this在静态方法。

http://php.net/manual/en/language.oop5.static.php

你可以检查一下,如果你在一个静态的背景下,虽然我怀疑这是否是矫枉过正...

class Foobar
{
  public static function foo()
  {
    $backtrace = debug_backtrace();
    if ($backtrace[1]['type'] == '::') {
      exit('foo');
    }
  }
}

另外也请注意-我相信 ,该方法是在静态情况下总是执行,即使它被称为上的一个实例。 我很高兴,如果我错了,虽然要在此更正。



Answer 2:

由于PHP是一个相当宽容的语言,你可以阻止这种默认行为,通过超载__callStatic ,也许使用反射来验证方法的范围。

http://php.net/manual/en/language.oop5.overloading.php#object.call

http://php.net/ReflectionClass



Answer 3:

我们可能需要对FooBar的声明更多的信息。 很显然,你不能声明两种方法FOO(),即使一个是一个静态方法,另一个实例方法:

class FooBar
{
  public static function foo()
  {
    return 'I am FooBar::foo().';
  }
  public function foo()
  {
    return 'I am FooBar->foo().';
  }
}
// result to Fatal error: Cannot redeclare FooBar::foo()

所以,我想,你想达到一个神奇的__call()方法,像这样:

class FooBar
{
  public $foo = 'I am FooBar->foo().'; 
  // yes we can have a property with the same name than a method

  // this is the static method that we want to avoid
  public static function foo()
  {
    return 'I am FooBar::foo().';
  }

  // this is the method that should be call
  public function __call( $method , $arguments = array() )
  {
    if( isset( $this->$method ) ) // or anything else
    {
      return $this->$method; // or anything else
    }
    else
    {
      // restore fatal error
      trigger_error( sprintf( 'Call to undefined method %s::%s()' , get_class( $this ) , $method ) , E_USER_ERROR );
    }
  }

}

为了实现这一目标,看这一段代码:

$foobar = new FooBar;

try
{
  // safe way to detect if a method is static
  // @see http://php.net/manual/en/class.reflectionmethod.php
  $rfx = new ReflectionMethod( get_class( $foobar ).'::foo' );
  if( $rfx->isStatic() )
  {
    // the method exists and is static
    // but we do not want to call it directly
    // why not involving the magic public method `__call()`?
    // sounds like a plan...
    echo $foobar->__call( 'foo' );
  }
  else
  {
    // the method exists and is not static
    echo $foobar->foo();
  }
}
catch( ReflectionException $e )
{
  // the method does not exist, let's do some kind of magic
  echo $foobar->foo();
}


文章来源: Why PHP uses static methods in object context?