企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
类与类之间有一种父与子的关系,子类继承父类的属性和方法,称为继承。在继承里,子类拥有父类的方法和属性,同时子类也可以有自己的方法和属性。 ``` <?php /** * User: 三千 * Date: 16/3/16 * Time: 下午4:17 */ class person{ public $name = 'Tom'; public $gender; static $money = 10000; public function __construct(){ echo '这里是父类',PHP_EOL; } public function say(){ echo $this->name,"\t is ",$this->gender,"\r\n"; } } class family extends person{ public $name; public $gender; public $age; static $money = 1000; public function __construct(){ parent::__construct(); echo '这里是子类',PHP_EOL; } public function say(){ parent::say(); echo $this->name,"\t is \t",$this->gender,",and is \t ",$this->age,PHP_EOL; } public function cry(){ echo parent::$money,PHP_EOL; echo '% >_< %',PHP_EOL; echo self::$money,PHP_EOL; echo "(*^_^*)"; } } $poor = new family(); $poor->name = 'Lee'; $poor->gender = 'female'; $poor->age = 25; $poor->say(); $poor->cry(); ``` 返回结果: ``` 这里是父类 这里是子类 Lee is female Lee is female,and is 25 10000 % >_< % 1000 (*^_^*)% ``` 在继承中,用parent指代父类,用self指代自己。 用“::”运算符调用父类方法,“::”操作符还用来作为类常量和静态方法的调用,不要把这两种应用混淆。 组合和继承都是提高代码可重用性的手段。在设计对象模型时,可以按照语义识别类之间的组合关系和继承关系。比如,继承是一种“是、像”的关系,而组合是一种“需要”的关系。利用这条规律,就可以很简单地判断出父亲与儿子应该是继承关系,父亲与家庭应该是组合关系。还可以从另一个角度看,组合偏重整体与局部的关系,而继承偏重父与子的关系。 从方法复用角度考虑,如果两个类具有很多相同的代码和方法,可以从这两个类中抽象出一个父类,提供公共方法,然后两个类作为子类,提供个性方法。这是用继承语意更好。 ![](https://box.kancloud.cn/2016-03-16_56e93de63615a.png) 组合就没有这么多限制。组合之间的类可以关系很小,甚至没有关系 ![](https://box.kancloud.cn/2016-03-16_56e93de6502f8.png) 在实际编程中,继承与组合的取舍往往并不是这么直接明了,很难说出二者是“像”的关系还是“需要”的关系,那么我们就要按照低耦合的标准来决定是继承还是组合。 耦合是一个软件结构内不同模块之间互连程序的度量,也就是不同模块之间的依赖关系。 低耦合指模块与模块之间,尽可能地使模块间独立存在;模块与模块之间的接口尽量少而简单。 解耦是要解除模块与模块之间的依赖。 如果这样子还没有办法区分两者,那么倾向于组合。 继承存在以下问题: - 1.继承破坏封装性。 定义鸟类为父类,具有羽毛属性和飞翔方法,其子类天鹅、鸭子、鸵鸟等继承鸟这个类。但是鸵鸟不需要飞翔的方法,但作为子类,他却可以使用飞翔这个方法,显然破坏了类的封装性。 - 2.继承是紧耦合的。 继承使得子类和父类捆绑在一起。组合仅通过唯一接口和外部进行通信,耦合度低于继承。 - 3.继承扩展复杂 随着继承层数的增加和自类的增加,将涉及大量方法重写,使用组合,可以根据类型约束,实现动态组合,减少代码。 - 4.不恰当地使用继承可能违反现实世界中的逻辑 比如,人作为父类 组合也有缺点,在创建组合对象时,组合需要一一创建局部对象,这一定程度上增加了一些代码,而继承则不需要这一步,因为子类自动有了父类的方法。 ``` <?php /** * User: 三千 * Date: 16/3/16 * Time: 下午6:57 */ class car{ public function addoil(){ echo "Add oil \r\n"; } } class bmw extends car{ } class benz{ public $car; public function __construct(){ $this->car = new car(); } public function addoil(){ $this->car->addoil(); } } $bmw = new bmw(); $bmw->addoil(); $benz = new benz(); $benz->addoil(); ``` 上面代码很显然,组合比继承增加了代码量。不过总体来说,优点大于缺点。 继承最大的优点就是扩展简单,但是其缺点大于优点,所以在设计时,需要慎重考虑。 使用继承的经验: - 精心设计专门用于被继承的类,继承树的抽象层应该比较稳定,一般不要多余三层 - 对于不是专门用于被继承的类,禁止其被继承,也就是使用final修饰符。使用final修饰符即可防止重要方法被非法覆写,又能给编辑器寻找优化的机会 - 优先考虑用组合关系提高代码的可重用性 - 子类是一种特殊的类型,而不只是父类的一个角色 - 子类扩展,而不是覆盖或者使父类的功能失效 - 底层代码多用组合,顶层/业务层代码多用继承。底层用组合可以提高效率,避免对象臃肿。顶层代码用继承可以提高灵活性,让业务使用更方便。