PHP:覆盖子类的父类属性

时间:2014-03-28 20:31:39

标签: php class oop override

也许你知道从子类方法

覆盖类属性的一些“正确方法”
<?php
class A {
  public $option;
  public function __construct() {
    $this->option = array(1,2,3);
  }

  public function bb() {
    $obj = new B;
    $obj->aa();

    print_r($this->option);die;
  }
}

class B extends A {

  public function __construct() {
    parent::__construct();
  }

  public function aa() {
    $this->option[] = 4;
    //print_r($this->option);die;
  }
}

$obj3 = new A;
$obj3->bb();
?>

返回Array ( [0] => 1 [1] => 2 [2] => 3 ),而不返回方法aa()

中的元素

是否可以从子类覆盖父类属性?

2 个答案:

答案 0 :(得分:2)

是的,您可以从子类覆盖父类属性,但在您的示例中,您正在实例化父类。您需要实例化子类,然后覆盖父属性

class A {
  public $option;
  public function __construct() {
    $this->option = array(1,2,3);
  }

  public function bb() {
    $obj = new B;
    $obj->aa();

    print_r($this->option);die;
  }
}

class B extends A {

  public function __construct() {
    parent::__construct();
  }

  public function aa() {
    $this->option[] = 4;
    print_r($this->option);die;
  }

}

$obj3 = new B;
$obj3->aa();

将输出

Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 ) 

答案 1 :(得分:2)

问题是你试图以一种完全没有意义的方式做某事。告诉你想要做什么有点困难,但希望如果你看看我的样本,它会告诉你发生了什么:

<?php

class BaseClass {
    /* If a property is public or protected it can be overriden in derived classes.
     * If you had made it private it wouldn't be changable in derived classes. 
     * If you make it also make it static then there is only one copy of it shared 
     * by all instances of the class (as well as those derived from it). */
    protected $option=array();

    public function __construct() {
        $this->option=array(1,2,3);
        /* We are in the base class so the reset() method doesn't exist yet.
         * This fails in this class: */
        // $this->reset();
    }
    /** Print the $option variable. */
    public function dump() {
        echo sprintf('<pre><b>%s</b> = ', get_class($this));
        print_r($this->option);
        echo "</pre>\n";
    }
}

class DerivedClass extends BaseClass {
    public function __construct() {
        parent::__construct();
        /* We have complete control over the variable BaseClass::$option from this class.
         * If we want to we can even make it a string instead of an array. */
        $this->option="I've overridden the option property.";
    }
    /** Reset the BaseClass::$option variable. */
    public function reset() {
        $this->option=array(1,2,3,4);
    }
}

/// Create a few test objects to play with
$objBase=new BaseClass();
$objDerived=new DerivedClass();

$objBase->dump(); // Display the base object data

/// If BaseClass::$option is public you can edit it directly here.
/// This may be easier but it is discouraged because it breaks OOP principals.
//$objDerived->option[]=5;

$objDerived->dump(); // Display the derived object data

$objDerived->reset(); // call a method which will change our data
$objDerived->dump(); // Display the derived object data again now

类提供了许多方法来进一步控制从当前类和外部派生的类可以看到的内容。这是通过使用public,protected和private关键字完成的。设置为public时,方法和属性对所有内容都可见,但它们仍然可能超出范围。简而言之,唯一的问题是你的方法B:aa()超出了A :: bb()的范围。

请记住,实际上BaseClass可能与DerivedClass不在同一个文件中,而某些项目可能不需要DerivedClass。如果你牢记这一点,你就不应该使用甚至没有被加载到项目中的方法。

在你的代码中,你在方法A :: bb()中创​​建了一个全新的B实例。这是一种几乎从未见过的设计模式,除了一些特定类型的函数(称为工厂函数,因为它们用于故意在基类中创建派生类)。我很确定这不是你在这里做的,因为这不是你经常在PHP中做的事情,因为PHP通常不会从文件中读取二进制类数据,而在其他情况下通常有更好的方法来完成工作。