【发布时间】:2010-10-11 08:09:16
【问题描述】:
任何现实世界中使用抽象类的简单示例? 我正在尝试进入 PHP 的 OOP,但我仍然无法理解 - 为什么应该使用抽象类以及何时使用(是的,我知道创建抽象类实例是不可能的,只有继承它的类实例)。
【问题讨论】:
任何现实世界中使用抽象类的简单示例? 我正在尝试进入 PHP 的 OOP,但我仍然无法理解 - 为什么应该使用抽象类以及何时使用(是的,我知道创建抽象类实例是不可能的,只有继承它的类实例)。
【问题讨论】:
也许您有一个图像类,并且您有 2 个驱动程序,GD 和 ImageMagick。
你的基类可能是
abstract class Image {
public function resize($width, $height) {
// Some prep code...
}
}
那么你的 GD 驱动会是这样的
class Image_Gd extends Image {
public function resize($width, $height) {
// Actual code
}
}
看看Kohana's source on GitHub。它有一个Image 类,即abstract。
【讨论】:
interface Image和制作Image_Gd implements Image就够了?
好的,假设您要加载脚本配置。该配置可以存储在数据库/XML/INI/YAML 文件中。每个驱动都要实现一些接口,我们称之为ConfigurationLoader。
interface ConfigurationLoader {
public function load();
public function get($key, $default = null);
}
// The final usage of the code:
$configuration = new XMLConfiguration('./some/file.xml');
$configuration = new YAMLConfiguration('./some/file.yaml');
$configuration = new DatabaseConfiguration($dbHandler, 'table_name');
$configuration->load();
echo $configuration->get('abc.def.ghi');
所以现在我们需要实现我们的驱动程序。您应该注意到的第一件事是基于文件的驱动程序可能工作相同。唯一的区别是它们每个都以不同的方式解析文件源。另一方面,数据库驱动程序的工作方式完全不同。
class DatabaseConfiguration implements ConfigurationLoader {
protected $config = array();
protected $pdo, $tableName;
public function __construct(PDO $dbHandler, $tableName) {
$this->pdo = $pdo;
$this->tableName = $tableName;
}
public function load() {
$this->config = /* fetch data from database */;
}
public function get($key, $default = null) {
return array_key_exists($this->config, $key) ? $this->config[$key] : $default;
}
}
现在我们需要实现 XML、INI 和 YAML 驱动程序。它们的工作方式几乎相同,所以...让我们创建一些处理通用代码的抽象类:
abstract class FileConfiguration implements ConfigurationLoader {
// Each file-based configuration loader has a constructor that takes file name as first argument
protected $filename;
public function __construct($filename) {
$this->filename = $filename;
$this->getFileContents();
}
// Each file-based driver has to store file content
protected $fileContent;
protected function getFileContents() {
$this->fileContents = file_get_contents($this->filename);
}
// Each driver will have to implement its own implementation of load().
// XMLConfiguration will parse XML, INIConfiguration will parse INI etc.
abstract public function load();
// However all of them will store parsed configuration in $config array:
protected $config = array();
public function get($key, $default = null) {
return array_key_exists($this->config, $key) ? $this->config[$key] : $default;
}
}
FileConfiguration 必须是抽象的,因为它不知道如何解析文件内容。只有交付的课程知道如何做到这一点:
class XMLConfiguration extends FileConfiguration {
public function load() {
$xml = simplexml_load_string($this->fileContents);
foreach ($xml->root as $config) {
$this->config[(string) $config->key] = (string) $config->value;
}
}
}
class YAMLConfiguration extends FileConfiguration {
public function load() {
$yaml = new SomeYAMLParser($this->fileContents);
foreach ($yaml->parse() as $config) {
$this->config[$config['key']] = $config['value'];
}
}
}
class INIConfiguration extends FileConfiguration {
public function load() {
...
}
}
正如您在此示例中所见,甚至可能还有一个抽象类 AbstractConfiguration 将存储 $config 属性和 get($key, $default = null) 方法,它将是 DatabaseConfiguration 和 FileConfiguration 的父类。
【讨论】: