1.为什么要面向对象
面向对象给我们一种忽略细节的能力,忽略的越多,人类有限的智力就可以容纳越多越复杂的问题,提高生产效率。我在这里先打个比方:我指挥一个人,他能够明白我的意思;我指挥100个人,我需要成立组织架构;我治理一个国家,需要有行政部门帮我管理;总理管理拥有13亿人口的中国,虽然智力和精力有限,但是他可以通过管理顶级部门。就这样,把具体的功能封装起来,我们可以忽略很多细节,我们的智商才够用。在java程序中,部门=类,人力资源部门=人力资源类,所有Java代码都以类为组织单元。
2.什么是面向对象
面向对象Object Oriented,简称OO;面向对象编程Object Oriented Programming简称OOP;面向对象是一种思想,面对事物的思考方式;Java就属于一种面向对象的语言。
3.面向对象和面向过程有什么区别
面向过程语言:提供小面积的问题解决思路;
面向对象语言:通过“封装、继承、多态”,让程序分析和设计能容纳更大的编程范围和系统规模。
面向过程==>蛋炒饭==>把米饭和鸡蛋混在一起炒==>如果不喜欢鸡蛋,需要倒掉炒饭重做;
面向对象==>盖浇饭==>把米饭和盖菜分开来搭配==>如果不喜欢盖菜,把盖菜拨掉重新加。
4.面向对象的三大基本特征
封装
封装的概念
封装就是把属于同一类事物的共性(包括属性与方法)归到一个类中,以方便使用。其中属性用来描述同一类事物的特征,方法描述一类事物可做的操作。
封装也称为信息隐藏,是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系。用户无需知道对象内部方法的实现细节,但可以根据对象提供的外部接口(对象名和参数)访问该对象。
封装的目的和作用
(1) 实现了专业的分工。将能实现某一特定功能的代码封装成一个独立的实体后,各程序员可以在需要的时候调用,从而实现了专业的分工。
(2) 隐藏信息、保证安全。尽量隐藏类中的属性和方法,只对外开放部分接口和外界联系,外部无法直接访问和修改类中属性,从而实现类和对象的安全性。
(3) 类的属性可以对外只读。
(4) 类可以完全控制自己的属性。
(5) 类可以修改属性的数据类型,而不会影响到外部的调用。
封装的操作步骤
(1) 将属性私有化
(2) 编写get和set方法
继承
继承的概念
子类中有一些共有的属性和方法,把这些共有的属性和方法提取出来,放到父类里,然后子类就可以继承这些属性和方法。
继承的目的和作用
使用继承可以优化设计,实现代码的复用。注意:继承后子类自动拥有了父类的属性和方法,但特别注意的是,父类的私有属性和构造方法并不能被继承。另外子类可以写自己特有的属性和方法,目的是实现功能的扩展,子类也可以复写父类的方法即方法的重写。
使用继承的条件
符合“is-a”关系的设计都可以用继承(例如:小猫是一种哺乳动物,藏獒是一种狗,金鱼是一种鱼等等)。
使用继承的注意事项
子类访问父类成员
子类访问父类成员的注意事项
(1) 使用super关键字,super代表父类对象 ;
(2) 在子类构造方法中调用且必须是第一句。
(3) 不可以访问父类中定义为private的属性和方法。
访问父类构造方法
Super(); //调用无参构造方法
Super(name); //调用带一个参数name的构造方法
Super(name,health);//调用带参数name和health的构造方法
访问父类方法
Super.getName(); //调用父类里的getName()方法
Super.print(); //调用父类里的print()方法
子类访问父类成员的小结
子类:如果子类里定义了带参构造,和无参构造,那么父类里必须有带参构造和无参构造。
子类:如果子类里没有带参构造和无参构造,那么默认调用父类的无参构造.
注意:
(1) 子类在没有通过this关键字调用自身的构造方法,也没有通过super关键字调用父类的构造方法,那么默认调用父类的无参构造方法。(顺序)先初始化父类的属性,再执行父类的无参构造,再执行子类的无参构造。
(2) 子类通过super(属性)调用父类的带参构造函数,那么只执行父类的带参构造和自己的带参构造,不会执行父类的无参构造。
(3) 如果子类通过this关键字调用自身的其他构造方法,那么在这些你调用的其他构造方法里应用以上两条A,B原则。
重写(overwrite)
重写的概念
子类根据需求对从父类那里继承得来的方法进行重新编写,注意重写时,可以用super.方法的方式来保留父类的方法,但是构造方法却不能重写。另外,方法重写又称为方法覆盖。
方法重写的规则
重载(overload)
重载的概念
重载和重写的区别
多态
多态的概念
多态概念的提出,是以封装和继承为基础的。多态是指相同的事物,调用其相同的方法,参数也相同时,但表现的行为却不同。多态的定义也可以表述为,同一个引用类型,使用不同的实例,而执行不同的操作。还可以表述为:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法(第三种表述来自百度官方)。正所谓万变不离其宗,尽管各种表述均有异同,但核心观点还是一致的,关键在于个人的理解。
多态的好处(网上已经有详细说明,笔者在此点到即止,不再赘述)
(1) 可替换性。多态对已存在代码具有可替换性。
(2) 可扩充性。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。
(3) 接 口 性。多态是父类通过方法签名,向子类提供了一个共同接口,由子类来重写或者重载它而实现的。
(4) 灵 活 性。它在应用中体现了灵活多样的操作,提高了使用效率。
(5) 简 化 性。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作。
多态存在的必要条件
(1) 要有继承;(2) 要有重写;
(3) 父类引用指向子类对象。
使用多态的注意事项
(1) 使用父类类型的引用,需要指向子类的对象;
(2) 该引用只能调用父类里面定义的方法和变量;面向对象三大基本原则的小结
(1)封装:封装隐藏了类的内部实现机制,可以在不影响使用者的前提下修改类的内部结构,同时保护了数据;5.面向对象的六大基本原则
里氏替换原则
里氏替换原则的概念
里氏替换原则,外文名为Liskov Substitution Principle,于1987年提出,官方给出的原始定义是:继承必须确保超类所拥有的性质在子类中仍然成立。
里氏替换原则的个人理解
按照里氏替换原则的定义,不难理解:任何基类可以出现的地方,子类一定可以出现。LSP是继承复用的基石,只有当衍生类可以替换掉基类,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的功能。
接口隔离原则
接口隔离原则的概念
客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
接口隔离原则的个人理解
接口隔离原则的含义是:建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中定义的方法尽量少,也就是说我们要为各个类建立专用的接口,而不要试图建立一个很庞大的接口供所有依赖于它的类去调用。
在程序设计中,依赖多个专用接口要比依赖一个综合的接口更加灵活。通过分散定义多个接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。
注意:单一职责原则和接口隔离原则看似很像,其实不然:一方面:单一职责原则注重的是职责;接口隔离原则则注重对接口依赖的隔离。另一方面:单一职责原则主要是约束类,其次才是接口和方法。它针对的是程序中的实现和细节。而接口隔离原则主要约束接口,主要针对抽象,针对程序整体框架的构建。
运用接口隔离原则一定要适度,接口设计的过小也不好,会使得接口数量过多,设计变得复杂化。
依赖置换原则
依赖置换原则的概念
程序要依赖于抽象接口,不要依赖于具体实现。该原则要求:对抽象进行编程,不需要对实现进行编程,降低客户与实现模块之间的耦合。
依赖置换原则的个人理解
面向过程的开发:上层调用下层,上层依赖于下层,当下层发生剧烈变动的时候,上层也要跟着变动,这会导致模块的复用性降低,而且加大了开发成本。
面向对象的开发:很好解决上面的问题,一般情况下,抽象的变化概率很小,让用户的程序依赖于抽象,实现的细节也依赖于抽象,这样做的话,即使实现细节不断变化,只要抽象不变,客户程序就不需要变化。大大降低客户程序与实现细节的耦合度。
开闭原则
开闭原则的概念
面向对象设计中,可复用设计的基石;软件实体对扩展开放,对修改关闭。
通俗地说:软件中系统中的各种组件,例如,模块、类、功能等,应该在不修改原有代码的基础上,引入新的功能。不必改动模块的源代码。
实现开闭原则的关键,在于“抽象”,把系统的所有可能的行为抽象成一个抽象底层。我们在实际开发过程的设计开始阶段,就需要罗列出系统所有可能的行为。它是面向对象设计的终极目标。
开闭原则的个人理解
单一职责原则
单一职责原则的概念
一个类或者模块应该有且只有一个改变的原因。
单一职责原则的个人理解
如果一个类承担的职责过多,就等于把这些职责耦合在一起了,一个职责的变化可能会削弱或者抑制这个类去完成其他职责的能力。此原则的核心就是实现:高内聚,低耦合。
注意:程序设计中,耦合发生常常是在不经意之间。究其原因,大都因为某种原因,某一职责被分化为颗粒度更细的多个职责了。解决方案:遵守单一职责原则,将不同的职责封装到不同的类或模块中。
迪米特法则(最少知道原则)
最少知道原则的概念
一个对象应当对其他对象有尽可能少的了解。一个实体应当尽可能少的与其他实体发生相互作用,每一个软件单位对其他的单位都只有最少的知识,而且局限于那些和本单位密切相关的软件单位。
最少知道原则的个人理解
迪米特法则的初衷是:降低类之间耦合,由于每个类尽量减少对其他类依赖,因此很容易使得系统的功能模块功能独立,相互之间没有或者很少有依赖关系。
迪米特法则不希望类之间建立直接的联系。如果真的又需要建立联系,则通过第三方(友元类)来实现转达。所以应用迪米特法则的后果会出现:系统中存在大量起传递作用的中介类,这在一定程度上增加了系统的复杂度。
未完待续……