【问题标题】:Calling Static Method from Class B(which extends Class A) of Class A从 A 类的 B 类(扩展 A 类)调用静态方法
【发布时间】:2009-02-05 15:27:05
【问题描述】:

练习测试中有一个有趣的问题,我不明白答案。以下代码的输出是什么:

<?php
class Foo {
    public $name = 'Andrew';

    public function getName() {
        echo $this->name;
    }
}

class Bar extends Foo {
    public $name = 'John';

    public function getName() {
        Foo::getName();
    }
}

$a = new Bar;
$a->getName();
?>

最初,我认为这是一个错误,因为静态方法不能引用 $this(至少在 PHP5 中)。我自己对此进行了测试,它实际上输出了 John。

我添加了 Foo::getName();在脚本的末尾,确实得到了我所期待的错误。那么,当您从扩展您调用的类的类中调用静态方法时,会发生什么变化?

有人介意详细解释一下这里发生了什么吗?

【问题讨论】:

    标签: php oop


    【解决方案1】:

    Foo::getName() 使用较旧的 PHP4 样式 scope resolution operator 来允许调用被覆盖的方法。

    在 PHP5 中,您将使用 parent::getName() 代替

    如果您想扩展而不是完全覆盖基类的行为,这很有用,例如这可能会更清楚

    class Bar extends Foo {
        public $name = 'John';
    
        public function getName() {
            echo "My name is ";
            parent::getName();
        }
    }
    

    【讨论】:

      【解决方案2】:

      如果调用绑定到其他对象的静态方法,该方法会在当前对象的上下文中执行。这允许访问 $this-object。

      从子类内部调用超类方法的更好方法是:

      parent::getName();
      

      【讨论】:

      • PHP 中有 super:: 符号吗?我唯一能想到的是 parent:: 用于静态类。
      【解决方案3】:

      $this 指向在其上下文中调用该方法的对象。所以:$this 是 $a->getName() 是 $a。 $fooInstance->getName() 中的 $this 将是 $fooInstance。如果设置了 $this(在对象 $a 的方法调用中)并且我们调用了静态方法,则 $this 仍然分配给 $a。

      使用此功能似乎会引起很多混乱。 :)

      【讨论】:

        【解决方案4】:

        当您调用$a-&gt;getName() 时,您正在引用一个特定对象$a,它属于Bar 类,因此返回“John”。

        Foo::getName() 在函数外无效,因为没有特定对象。

        我不确定它在 PHP 中是否有效,但如果您像 (Foo)$a-&gt;getName() 那样将对象cast 转换为超类,那么您的结果将是“Andrew”。您仍然在谈论特定对象 ($a),但在本例中为 Foo。 (请注意,您通常不想这样做

        【讨论】:

          【解决方案5】:

          有时程序员比用英语更善于用代码解释事物!

          这里发生的第一件事是重载的概念。当你实例化 Bar 时,它的 getName() 方法重载了 Foo 中的同名方法。

          重载是OOD的一个强大而重要的部分。

          但是,能够调用存在于父类 (Foo) 中的方法的版本通常很有用。

          这是一个例子:

          class Dog
          {
             public function getTag()
             {
                return "I'm a dog.";
             }
          }
          
          class Skip extends dog
          {
             public function getTag()
             {
                return Dog::getTag() . " My name is Skip.";
                // I'm using Dog:: because it matches your example. However, you should use parent:: instead.
             }
          }
          
          $o = new Skip();
          echo $o->getTag(); // Echo's: "I'm a dog. My name is Skip."
          

          显然这是一个非常狭隘的例子,但它说明了一点。

          您的基类是类型的最通用实现。在这种情况下,它是“狗”。您希望将信息放在该类型的所有实例通用的这个基类中。这可以防止每个派生类中的重复(如“跳过”)。

          您的脚本可能无意中利用了此功能。

          【讨论】:

            最近更新 更多