理解组合对象与类继承

  

1.概念解析

  • 继承:"继承"是面向对象编程中的一个概念。

    面向对象编程的单一职责原理(SPR-Single Responsibility Principle)规定对象只能有一个职责。就一个类而言,应该仅有一个引起它变化的原因。 为什么要把不同的职责分配到不同的类中呢?因为每一个职责都是变化的一个轴线,当需求变化时,该变化会反映为类的职责的变化。如果一个类承担了多于一个的职责,那么就意味着引起它的变化的原因会有多个。如果一个类承担的职责过多,那么就等同于把这些职责耦合在了一起。一个职责的变化可能会抑制到该类完成其他职责的能力,这样的耦合会导致脆弱的设计。当变化发生时,设计会受到意想不到的破坏。

    这个原则的核心含意是:一个类应该有且仅有一个职责。关于职责的含意,面向对象大师Robert.C.Martin有一个著名的定义:所谓一个类的职责是指引起该类变化的原因,如果一个类具有一个以上的职责,那么就会有多个不同的原因引起该类变化,其实就是耦合了多个互不相关的职责,就会降低这个类的内聚性。

    例如我们现在有两个类,D和C。那么类D的对象可以使用仅对类C对象有效的方法或属性,它使得这些方法和属性就像是由D定义的。这时,C是D的父类,D是C的子类。由于在继承过程中,父类的内部细节对子类完全可见,因此通过继承的代码复用被称为“白盒式代码复用”(white-box reuse)。

    因此,当你通过从另一个对象继承的方式来创建一个新的对象时,目标就应该是使得新的对象有一个相对于原始对象更加特定的版本。

  • 对象组合(组合对象):将多个元素作为一个对象来处理,需要将它们组合。

    一个对象可以把对象作为自己的成员变量,如果用这样的类创建对象,那么该对象中就会有其它对象,也就是说该对象将其他对象作为自己的组成部分(这就是人们常说的Has-A),或者说该对象是由几个对象组合而成。

    对象组合就是通过对现有的对象进行拼装(组合)产生新的、更复杂的功能,而由于对象之间各自内部细节不对外可见,所以这种方式的代码复用被称为“黑盒式代码复用”(black-box reuse)。对象组合要求被组合的对象具有良好定义的接口。

  举例:

<?php

class person{

  public $name;

  public $gender;

  public function say(){

    echo $this->name," \tis ",$this->gender,"\r\n";

  }

}

class family{

  public $people;

  public $location;

  public function construct($p,$loc){

    $this->people=$p;

    $this->location=$loc;

  }

}

$student=new person();

$student->name=‘Tom‘;

$student->gender=‘male‘;

$student->say();

$tom=new family($student,‘peking‘);

  以上代码中,定义了两个类,一个是person,一个是family;在family类中创建person类中的对象,把这个对象视为family类的一个属性,并调用它的方法处理问题,这种复用方式就叫“组合”。

 

2、继承与组合区别

  类继承是在编译时刻静态定义的,且可直接使用,因为程序设计语言直接支持类继承。类继承可以较方便地改变被复用的实现。当一个子类重定义一些而不是全部操作时,它也能影响它所继承的操作,只要在这些操作中调用了被重定义的操作。
  但是类继承也有一些不足之处。首先,因为继承在编译时刻就定义了,所以无法在运行时刻改变从父类继承的实现。更糟的是,父类通常至少定义了部分子类的具体表示。因为继承对子类揭示了其父类的实现细节,所以继承常被认为“破坏了封装性” 。子类中的实现与它的父类有如此紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。当你需要复用子类时,实现上的依赖性就会产生一些问题。如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性。一个可用的解决方法就是只继承抽象类,因为抽象类通常提供较少的实现。

 对象组合是通过获得对其他对象的引用而在运行时刻动态定义的。组合要求对象遵守彼此的接口约定,进而要求更仔细地定义接口,而这些接口并不妨碍你将一个对象和其他对象一起使用。这还会产生良好的结果:因为对象只能通过接口访问,所以我们并不破坏封装性;只要类型一致,运行时刻还可以用一个对象来替代另一个对象;更进一步,因为对象的实现是基于接口写的,所以实现上存在较少的依赖关系。

  对象组合对系统设计还有另一个作用,即优先使用对象组合有助于你保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物。另一方面,基于对象组合的设计会有更多的对象 (而有较少的类),且系统的行为将依赖于对象间的关系而不是被定义在某个类中。
  这导出了我们的面向对象设计的第二个原则:优先使用对象组合,而不是类继承。

推荐阅读》》

面向对象编程中的继承和组合的简单比较

面向对象的编程概念:组合(Composition)和聚合(aggregation)

时间: 2024-11-09 05:00:04

理解组合对象与类继承的相关文章

【JavaScript】类继承(对象冒充)和原型继承__深入理解原型和原型链

JavaScript里的继承方式在很多书上分了很多类型和实现方式,大体上就是两种:类继承(对象冒充)和原型继承. 类继承(对象冒充):在函数内部定义自身的属性的方法,子类继承时,用call或apply实现对象冒充,把类型定义的东西都复制过来,这样的继承子类与父类并没有多少关联,不互相影响,有利于保护自身的一些私有属性. 原型继承:每个函数都有自己的原型(prototype)属性,这个属性是在生成实例对象时自动创建的.它本身又是一个对象,拥有能够在实例间共享的属性和方法.而实例本身的属性和方法,则

类的继承、派生、组合、菱形的继承、多态

类的继承 继承是一种新建的类的方式,新建的类成为子类,被继承的类称为父亲 继承的特性是:子类会遗传父亲的属性 继承是类与类之间的关系 使用继承目的,可以减少代码的咒余 在python中,父类和子类只有在继承的时候才会产生 继承是为了拿到父类的所有东西 class Parent_Foo: def __init__(self,first_name,money,car,house) self.first_name = first_name self.car = car self.house =hous

core JAVA 学习篇之深入理解对象与类

一.面向对象概述 1.面向对象程序设计(OOP): (1)由对象组成,每个对象包含,对用户公开的特定的功能部分,和隐藏的实现部分. (2)如果对象能够满足需求,则不必关心其功能的实现过程. (3)与结构化程序设计区别: 结构化程序设计:Algorithms + Data Structures = Programs;算法是第一位的,数据结构是第二位的.程序员首先确定如何操作数据,然后确定如何组织数据. 面向对象程序设计:Data Structures + Algorithms = OOP:OOP将

深入理解Java对象的创建过程:类的初始化与实例化

"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 深入理解Java对象的创建过程:类的初始化与实例化 - Rico's Blogs - 博客频道 - CSDN.NET Rico's Blogs 潜心修炼,成为一个更好的人. 目录视图 摘要视图 订阅 [活动]2017 CSDN博客专栏评选 &nbsp [5月书讯]流畅

C++ 类继承与对象赋值 情况下 成员变量的覆盖 浅析

[摘要] 类的继承以及对象的赋值会带来成员变量的相互传递.这里详细讨论了,类间继承带来的成员变量的传递采用覆盖原则,采用函数级的成员变量的取值:对象赋值带来的成员变量的传递采用,实函数采用数据类型的实函数,虚函数采用赋值源的虚函数,成员变量采用赋值源的成员变量,其实也是函数级的成员变量. [正文] 在类继承中,成员变量存在覆盖的情况,成员函数则存在隐藏和覆盖以及重载的情况.在类继承中,公有继承会导致公有成员变量的覆盖,从而使得成员函数的调用出现各种结果. [代码示例 01] #include<i

对象冒充实现继承,原型链继承方法,以及组合继承模式

function Person (){ this.name=“张三”; this.run = function(){ alert( this.name+'在运动' ) } } Person.prototype.work = function(){ alert( this.name+'在工作’ ) } // web类 继承person类 原型链+对象冒充的组合继承模式 function web(){ Person.call( this )  //  对象冒充实现继承 } var w = new w

对象和类的理解

什么是对象 程序中的对象是对现实对象的抽象.现实中的对象包括可感知的物体以及思维中的概念.例如,天鹅.闹钟.飞机等各种物体可以看做一个个的对象,学校.公司.家庭等概念也可以看做一个个的对象.现实对象有一个特点,即它是具有属性和行为的整体.例如一个闹钟具有当前时间刻度.预定时间等“属性”,并具有指示时间.响铃等“行为”:而学校则具有学生.教师等“属性”,并具有招生.教育等“行为”.在程序中,属性可以抽象成数据,而行为可以抽象成函数,一个数据和函数的集合就构成了一个对象. 提示 程序中的对象是一个整

关于对象、类、属性和方法的理解

文章开头申明:半路出家的野路子,可能个人理解有所欠缺,希望不吝赐教. 在初步学习java的过程中,往往都是绕不开面向对象的思想,说到对象或许挺多初学者和我一样只是听说过一个"万物皆对象"的说法,简单的记下对象包含属性和方法,然而实际使用的过程中往往有忽略这些东西,也就是犯浑了.个人的理解是希望将对象.类.属性和方法用一个例子来简单说明. 打个比方说我到商场买手机这个例子吧.我到了商场买手机,第一步自然就是向售货员提出我的要求:如手机大小.CPU.内存等等(属性),要求能拍照打电话首发短

C++ 类继承的对象布局

C++多重继承下,对象布局与编译器,是否为虚拟继承都有很大关系,下面将逐一分析其中的差别,相同点为都按照类继承的先后顺序布局(类内按照虚表.成员声明先后顺序排列).该类情况为子类按照继承顺序排列,如class C:public B,public A此种情况布局如下: 如果class B,A带有虚函数,情况又发生了变化: 考虑下面的情况: class D { int d; public: virtual void fun() {} virtual ~D() {} }; class E { publ