面向對象不僅僅是一個類的外觀和操作方式。這也是關於一個或多個類的實例如何一起工作。
這就是爲什麼你看到很多基於「汽車」和「人」的例子,因爲他們真的很好地闡明瞭這個原理。
在我看來,OOP最重要的課程是封裝和多態性。
封裝:耦合數據和作用於那個數據一起以簡明,合乎邏輯的方式的邏輯 多態性:一個對象看起來狀和/或行爲狀另一個的能力。
一個很好的現實世界的例子就像一個目錄迭代器。這個目錄在哪裏?也許它是一個本地文件夾,也許它像FTP服務器一樣遠程。誰知道!
這是一個基本分類演示封裝:
<?php
interface DirectoryIteratorInterface
{
/**
* @return \Traversable|array
*/
public function listDirs();
}
abstract class AbstractDirectoryIterator implements DirectoryIteratorInterface
{
protected $root;
public function __construct($root)
{
$this->root = $root;
}
}
class LocalDirectoryIterator extends AbstractDirectoryIterator
{
public function listDirs()
{
// logic to get the current directory nodes and return them
}
}
class FtpDirectoryIterator extends AbstractDirectoryIterator
{
public function listDirs()
{
// logic to get the current directory nodes and return them
}
}
每個類/對象是負責自己的檢索目錄列表的方法。數據(變量)與使用數據的邏輯(類功能,即方法)耦合。
但是故事還沒有結束 - 請記住我說OOP是關於類的實例如何協同工作,而不是任何單個類或對象?
好吧,讓我們對這些數據做些什麼 - 將其打印到屏幕上?當然。但是如何? HTML?純文本? RSS?讓我們解決這個問題。
<?php
interface DirectoryRendererInterface
{
public function render();
}
abstract class AbstractDirectoryRenderer implements DirectoryRendererInterface
{
protected $iterator;
public function __construct(DirectoryIteratorInterface $iterator)
{
$this->iterator = $iterator;
}
public function render()
{
$dirs = $this->iterator->listDirs();
foreach ($dirs as $dir) {
$this->renderDirectory($dir);
}
}
abstract protected function renderDirectory($directory);
}
class PlainTextDirectoryRenderer extends AbstractDirectoryRenderer
{
protected function renderDirectory($directory)
{
echo $directory, "\n";
}
}
class HtmlDirectoryRenderer extends AbstractDirectoryRenderer
{
protected function renderDirectory($directory)
{
echo $directory, "<br>";
}
}
好了,現在我們必須遍歷和渲染目錄列表一對夫婦類樹木。我們如何使用它們?
// Print a remote directory as HTML
$data = new HtmlDirectoryRenderer(
new FtpDirectoryIterator('ftp://example.com/path')
);
$data->render();
// Print a local directory a plain text
$data = new PlainTextDirectoryRenderer(
new LocalDirectoryIterator('/home/pbailey')
);
$data->render();
現在,我知道你在想什麼,「但是彼得,我不需要這些大的班級樹來做到這一點!」但如果你認爲那麼你就錯過了這一點,就像我懷疑你一直在「車」和「人」的例子。不要專注於示例的細節 - 而是試着瞭解這裏發生了什麼。
我們已經創建了兩個類樹木,其中一個(*DirectoryRenderer
)使用其他(*DirectoryIterator
)以預期的方式 - 這通常被稱爲合同一個。 *DirectoryRenderer
的一個實例並不關心它接收哪種類型的實例*DirectoryIterator
,也不關心*DirectoryIterator
如何渲染它們。
爲什麼?因爲我們是這樣設計的。他們只是插在一起工作。 這是操作中的OOP。
**請參閱:**「無行爲比較OOP vs程序」: http://stackoverflow.com/questions/1530868 – dreftymac 2009-12-04 18:26:34