【问题标题】:Is there any polymorphism in PHP?PHP中有任何多态性吗?
【发布时间】:2011-08-02 08:14:38
【问题描述】:

假设baseson 类都有一个方法method_1

还有另一种方法method_2 of base

base::method_2内部,无论$thisbase还是son的实例,我如何将$this->method_1指向base::method_1

【问题讨论】:

  • 你说的不是多态。忽略子类对方法的重新实现?你为什么要这样做?
  • @meagar,我同意。如果你不希望它被覆盖,它应该是privatefinal
  • 您应该将问题的标题编辑为“PHP OOP Hierarchy 出现问题”或“如何绕过继承 - PHP OOP”...当前具有误导性。

标签: php oop polymorphism


【解决方案1】:

如果我理解正确,你想要这样的东西:

<?php

class base {
  public function method1() {
    echo "base:method1\n";
  }
  public function method2() {
    if(get_class($this) == 'base') {
      $this->method1();
    }
    else {
      parent::method1();
    }
    echo "base:method2\n";
  }
}



class son extends base {
  public function method1() {
    echo "son:method1\n";
  }
}


$obj = new son();

$obj->method2();

对方法 2 的调用将始终使用方法 1 的基本版本。

我能做到的最好方法是如上,但由于 base 没有父级,此代码不起作用。我很确定你想要做的事情是不可能的。

这是您将得到的错误:

PHP Fatal error:  Cannot access parent:: when current class scope has no parent in 

【讨论】:

    【解决方案2】:

    将函数设为私有:

    <?php
    class A
    {
      public function __construct()
      {
        $this->foo();
        $this->bar();    
      }
    
      private function foo() { echo "A::foo()\n"; }
      public function bar() { echo "A::bar()\n"; }
    }
    
    class B extends A
    {
      public function foo() { echo "B::foo()\n"; }
      public function bar() { echo "B::bar()\n"; }
    }
    
    new B();
    ?>
    

    输出是:

    A::foo()
    B::bar()
    

    【讨论】:

    • 你所说的这个规范是什么,你为什么希望 PHP 遵守它?
    【解决方案3】:

    是的。它是单数的(单亲)。

    son-&gt;method_1 可以添加或覆盖所有base-&gt;method_1 功能。

    son-&gt;method_1 可以简单地添加一个附加功能,并利用其父级实例method_1 的其余功能

    所以调用$this-&gt;method_1 将使用base-&gt;method_1son-&gt;method_1,只要你想从base 使用的东西没有被儿子覆盖。

    【讨论】:

      【解决方案4】:

      如果你调用了一个在你的子类中不存在的方法,PHP 将遍历类层次结构,直到找到实现你想要的函数的祖先类。这意味着如果你的son 类没有实现method_2,PHP 将自动寻找最近的祖先。在您的情况下,它会根据需要调用 method_2base

      如果您正在在您的son 类中覆盖method_2,并且您想要自己实现method_2 并调用base::method_2 实现 em> 那么你可以使用parent 关键字:

      class son extends base {
        public function method_2() {
          parent::method_2();
          //do son::method_2()-specific stuff here
        }
      }
      

      您不能将parent 调用链接在一起,因此如果baseGrandparentClass 的子类,您就不能这样做:

      parent::parent::method_2(); // trying to call grandparent::method_2
                                  // but this call will fail
      

      但是你可以直接通过名字来引用祖先类,这样就可以了:

      GrandparentClass::method_2();
      

      更进一步,还有一个名为class_parents() 的函数,它返回您的类继承自的每个祖先类的数组。如果您想返回两个祖先,但由于某种原因您不知道其具体名称,这可能会有所帮助,您仍然可以使用 eval() 调用该函数。

      例如,此代码将调用GrandparentClass::method_2(),而无需在代码中直接按名称引用该类:

      $parents = class_parents($this);
      eval(end($parents) . "::method_2();");
      

      希望对您有所帮助。

      【讨论】:

        【解决方案5】:

        这会做你想做的事。向 dbers 提供示例代码的道具(即使他的不太好用)。

        <?php
        
        class base {
          public function method1() {
            echo "base::method1\n";
          }
          public function method2() {
            if (get_parent_class($this) === FALSE) {
              echo get_class($this)." has no parent\n";
              $this->method1();
            } else {
              echo get_class($this)." has parent\n";
              call_user_func(array(get_parent_class($this), 'method1'));
            }
          }
        }
        
        class son extends base {
          public function method1() {
            echo "son::method1\n";
          }
        }
        
        $b = new base();
        $b->method2();
        
        $s = new son();
        $s->method2();
        
        ?>
        

        输出:

        base has no parent
        base::method1
        son has parent
        base::method1
        

        【讨论】:

          猜你喜欢
          • 2010-09-15
          • 2011-05-12
          • 2020-05-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-02
          • 1970-01-01
          • 2011-07-14
          相关资源
          最近更新 更多