您的位置:首页 > 编程语言 > PHP开发

面向对象三大特性--封装、继承、多态

2018-02-26 16:28 561 查看

封装

简单地说,封装就是对客户端代码隐藏数据和功能。封装也是面向对象的重要概念之一。

要实现封装,最简单的办法是将属性定义为
private
protected
。通过对客户端代码隐藏属性,我们创建了一个接口并防止在偶然情况下污染对象中的数据。

多态
是另外一种封装。通过把不同的实现放在公共接口之后,我们对客户端代码隐藏了功的实现。也就是说,任何在接口背后发生的改变对外界的系统来说都是可忽略的。我们可以增加新类或改变类中的代码,而不会产生错误。接口与其背后的工作机制是分开来的。这些机制越独立,改进或修改代码对系统的影响越小。

从某种程度上来说,封装是面向对象编程的关键。我们的目标是使系统中的每一部分都尽可能独立。类和方法应当能够接收到足够的信息来执行它承担的任务,而这些任务应该非常清晰,有明确的定义和范围。

在PHP5版本以上,我们可以在需要类选择时打破常规,使用
instanceof
操作符来找出所用对象属于哪一个具体的子类。

function subjectWithStudy (Study $subject)
{
if ($subject instanceof PhpClass) {
// php科目特有的操作

} elseif ($subject instanceof JavaClass) {
// java科目特有的操作

}
}


这样做通常有很好的理由,但通常来说会带来一些不确定的因素。在代码中查询特定子类型时会产生一个依赖关系。如果我们利用多态来隐藏子类型的特性,
Study
的继承关系改变就不会产生任何错误。但上面的代码会破坏这种情况。使用上面的代码时,如果我们改写了
PhpClass
JavaClass
类,就有可能在
subjectWithStudy()
方法中产生预想不到的错误。

这个例子说明了两件事

首先,封装可以帮助我们创建
正交
(指非常独立的,依赖性很小的)代码。

其次,封装的范围不怎么重要,无论封装的规模是大是小,类和客户端代码都必须同时关注封装的实现。

继承

如果一个类A继承自另一个类B,就把这个A称为“B的子类”,而把B称为“A的父类”。继承可以使得子类具有父类的各种属性和方法,而不需要再次编写相同的代码。在令子类继承父类的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类的原有属性和方法,使其获得与父类不同的功能。另外,为子类追加新的属性和方法也是常见的做法。

class Shoes {
private $name;
public $type;

protected function getShoeName($name)
{
$this->name = $name;
$shoesName = '这双鞋子的名称叫' . $this->name;
return $shoesName;
}
}

class Nike extends Shoes {

private $name = 'Nike';

public function getName()
{
$res = $this->getShoeName($this->name);
return $res;
}
}
$nike = new Nike;
$resp = $nike->getName();
var_dump($resp);


response:这双鞋子的名称叫Nike

Nike类中的
getShoeName
是继承了父类 Shoes 之后才有的方法。

继承方式常使用如下三种关键字给予表示

public
- 所有代码都可访问

private
- 只有当前类可以访问

protected
- 只有当前类和它的子类可以访问

多态

多态或称“类切换”是面向对象系统的基本特性之一。

多态是指在一个公用接口后面维护多个实现。如果代码中存在大量条件语句,就说明需要使用多态。

多态的实现是离不开继承的,没有继承就没有多态。

/**
* 定义抽象基类
*/
abstract class ParamHandler {
protected $source;
protected $params = array();

function __construct($source)
{
$this->source = $source;
}

function addParam($key, $val)
{
$this->params[$key] = $val;
}

function getAllParasms()
{
return $this->params;
}

static function getInstance() {
if (preg_match("/\.xml$/i", $filename)) {
return new XmlParamHandler($filename);
} else {
return new TextParamHandler($filename);
}
}

abstract function write();

abstract function read();
}

/**
* xml具体子类
*/
class XmlParamHandler extends ParamHandler {

function read()
{
//读取xml文件内容
}

function write()
{
//写入xml文件
}
}

/**
* text具体子类
*/
class TextParamHandler extends ParamHandler {

function read()
{
//读取text文件内容
}

function write()
{
//写入text文件
}
}

$test = ParamHandler::getInstance($file);
$test->read(); //可能是XmlParamHandler::read()或TextParamHandler::read()
$test->addParam('subject', 'php');
$test->write(); //可能是XmlParamHandler::write()或TextParamHandler::write()


要特别注意的是多态并没有消除条件语句。像
ParamHandler::getInstance
这样的方法经常要通过 switch 或 if 语句决定要返回的对象,但
多态可以把条件代码集中到一个地方


就像我们看到的那样,PHP强制接口由抽象类定义。这非常有用,因为我们可以确定子类将会实现父类中定义的所有方法,包括类型提示和方法的访控制。客户端代码因此可以使用一个公共父类的任意子类而不需要改写代码(只要客户端代码仅依赖于父类中定义的功能)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息