PHP抽象类不会影响其子项的子项

时间:2014-05-16 03:58:36

标签: php class parent abstract

我有一个抽象类,声明其子元素所需的方法。它还有一个孩子继承的委托人。如何使抽象类影响扩展它的类的子类。为了进一步澄清我的问题,我的情况如下:

抽象类(abstract.php):

<?php
include_once 'database.php';
include_once 'validation.php';

abstract class DataOperations extends DatabaseConnection {
  //The error string shared by all children of DataOperations
  //This will be the message to be displayed in case validation failure
  public $validator;
  public $err_valid_string;
  /**
  * The DataOperations' constructor ensures that all of its children can perform database operation
  * by automatically starting it for them. In case a child overrides this constructor, this child
  * must explicitly start the connection to prevent fatal errors. Also, $validator must be re-instantiated
  */
  public function __construct() {
    $this->startDBConnection();
    $this->validator = new InputValidator();
  }
  public function __destruct() {
  }

  abstract public function validateData();
  abstract public function loadRecord($key, $cascade);
  abstract public function saveRecord();
  abstract public function updateRecord();
  abstract public function deleteRecord();
}
?>

现在,这是扩展DataOperations抽象类的子对象     

class Guest extends DataOperations {
  //some properties here

  public function validateData() {
    //implementation
  }

  public function newRecord(implementation) {
    //implementation
  }

  public function loadRecord($key, $cascade){
    //implementation
  }

  public function saveRecord() {
    //implementation
  }

  public function updateRecord() {
    //implementation
  }

  public function deleteRecord() {
    //implementation
  }
}
?>

这是另一个班,是宾的孩子     

class Booking extends Guest {
  //some properties here

  public function validateData() {
    //implementation
  }

  public function newRecord(implementation) {
    //implementation
  }

  public function loadRecord($key, $cascade){
    //implementation
  }

  public function saveRecord() {
    //implementation
  }

  public function updateRecord() {
    //implementation
  }

  public function deleteRecord() {
    //implementation
  }
}
?>

问题是,如果我在Booking中删除一个方法,比如deleteRecord(),PHP就不会抛出错误,因为我认为抽象类不会影响它的'孙子'。我怎样才能解决这个问题?我想过使用接口,但我的系统已经有11个类,这些类依赖于抽象类的某些方法。这将需要密集的重构。

3 个答案:

答案 0 :(得分:0)

最好和最干净的方法是让你的&#34;预订&#34; class扩展&#34; DATAOPERATIONS&#34; class,而不是GUEST,因为看起来你在BOOKING类中没有任何额外的方法。其他明智的制作和接口并实现它。这不是首选方式,但您必须提供更多信息。

答案 1 :(得分:0)

要清楚,重新声明子类中的方法将在从子类调用时覆盖父类的该方法的实现,同时不影响通过扩展父类提供的任何其他功能:

class a 
{
    function hello()
    {
        echo "Hello";
    }

    function goodbye()
    {
        echo "Goodbye";
    }
}

/**
 * class b overwrites class a's implementation of method goodbye but will retain
 * it's definition for method hello
 */
class b extends a
{
    function goodbye()
    {
        echo "See ya!";
    }
}

$object = new b();
$object->hello();  // Hello
$object->goodbye();// See ya!

您似乎希望跨多个类定义实现一致的接口。如果是这种情况,您可能希望使用PHP的接口进行探索。

这些允许您指定类定义中必须存在的方法及其参数集(统称为签名)。您的类定义将implement一个接口,如果您的定义不符合接口实现规范,则会抛出致命错误。

从PHP手册:

// Declare the interface 'iTemplate'
interface iTemplate
{
    public function setVariable($name, $var);
    public function getHtml($template);
}

// Implement the interface
// This will work
class Template implements iTemplate
{
    private $vars = array();

    public function setVariable($name, $var)
    {
        $this->vars[$name] = $var;
    }

    public function getHtml($template)
    {
        foreach($this->vars as $name => $value) {
        $template = str_replace('{' . $name . '}', $value, $template);
    }

    return $template;
}


// This will not work
// Fatal error: Class BadTemplate contains 1 abstract methods
// and must therefore be declared abstract (iTemplate::getHtml)
class BadTemplate implements iTemplate
{
    private $vars = array();

    public function setVariable($name, $var)
    {
        $this->vars[$name] = $var;
    }
}

您可以在PHP手册中找到有关界面的更多信息:

http://us2.php.net/interface

最后,看起来您希望为子类定义一个公共构造函数。您的子类可以在实现单独的接口时扩展DataOperations类:

class Guest extends DataOperations implements DatabaseWriter
...

答案 2 :(得分:0)

正如您自己所说,界面是最适合的解决方案。像

include_once 'database.php';
include_once 'validation.php';

interface DbInterface {
  abstract public function validateData();
  abstract public function loadRecord($key, $cascade);
  abstract public function saveRecord();
  abstract public function updateRecord();
  abstract public function deleteRecord();
}

class DataOperations extends DatabaseConnection {
  //The error string shared by all children of DataOperations
  //This will be the message to be displayed in case validation failure
  public $validator;
  public $err_valid_string;
  /**
  * The DataOperations' constructor ensures that all of its children can perform database operation
  * by automatically starting it for them. In case a child overrides this constructor, this child
  * must explicitly start the connection to prevent fatal errors. Also, $validator must be re-instantiated
  */
  public function __construct() {
    $this->startDBConnection();
    $this->validator = new InputValidator();
  }
  public function __destruct() {
  }

}

class Guest extends DataOperations implements DbInterface {
    - - -
}

class Booking extends Guest implements DbInterface {
    - - -
}

首先,当你看到我从父类中删除了抽象时,因为我假设只有那些方法是抽象的。第二,根据你的11个类的问题依赖于抽象类,我会说当你只删除抽象方法时,现在实现抽象方法的类应该实现接口。这是一次所需的任务。虽然使用其他常规抽象类方法的类像以前一样工作。