前言
一、面向对象的三大特性
1. 封装
2.继承
3.多态
二、面向对象七个设计原则
1.单一职责原则
2.开放封闭原则
3.里氏替换原则
4.接口隔离原则
5.依赖倒置原则
6.合成复用原则
7.迪米特法则
三、可能的面试题
1. 面向对象和面向过程的区别是什么/p>
2. 面向对象的特征有哪些/p>
3. 什么是多态机制ava语言如何实现多态的/p>
4. 讲讲重写和重载的区别载的方法能否根据返回类型区分/p>
5. 构造器能否被重写/p>
6.面向对象的五大基本原则是什么/p>
7.抽象类和接口有什么区别/p>
前言
最近在买书的时候为了那个满100减50的图书品类券顺手拼上的一本《大话设计模式》,闲来无事或者睡前翻两页,倒是让我有点可惜没有早点看看设计模式就开始盲目为了工作内容而瞎敲代码,代码评审的时候大佬们提出的宝贵意见竟然发现写在书本的最前面,但之前没有看也就不会有意识到自己的问题所在。
大学那会儿学习设计模式就是为了面试答题,所以觉得设计模式是个虚无缥缈的东西,知道设计模式是什么竟也没想着写代码的时候为了用着它,后来被假大空的架构演进被逼套入设计模式的时候开始吐槽没必要。设计模式是什么呢们写代码用了设计模式了就是好代码了为了设计模式写符合某设计模式的代码么/p>
设计模式是针对某个场景在代码实现以后,逐渐形成的一套优秀的解决方案,所以应该在合适的位置使用合适的设计模式,既不是为了套用设计模式写代码也不是写代码完全不考虑设计模式。此篇以书中介绍的基础知识先做一个铺垫性的概述。
近期置顶语:“纸上得来终觉浅,绝知此事要躬行。”
一、面向对象的三大特性
1. 封装
封装主要分为两方面的含义:一方面是封装数据和方法(定义类),另一方面是控制访问权限(访问修饰符)。
基本封装单位是类。由于类的用途是封装复杂性,所以类的内部有隐藏实现复杂性的机制。Java 提供了私有和公有的访问模式,类的公有接口代表外部的用户应该知道或可以知道的每件东西,私有的方法数据只能通过该类的成员代码来访问。
2.继承
继承是子类继承父类,或者专业一点叫做派生类和基类。在继承关系中,子类可以继承父类非private的属性和功能,且子类可扩展父类没有的属性和方法,第三子类可以用自己的方式去重写父类的方法。
3.多态
“一个接口,多个方法”。多态性体现在父类中定义的属性和方法被子类继承后,可以具有不同的属性或表现方式。多态性允许一个接口被多个同类使用,弥补了单继承的不足。
那天和室友聊天的时候一时没想起来怎么描述,就举了个例子:动物类有个“发出声音”方法,人继承它就是“说话”,狗继承它就叫做“犬吠”……嗷 然后被室友打了,她说我仿佛在骂她
二、面向对象七个设计原则
1.单一职责原则
简称SRP(Single Responsibility Principle)原则,每个类型(包括接口和抽象)功能要求单一,只负责一件事情,不能包罗万象。
例如一个 Modem(调制解调器)的接口
这个接口中存在两个职责:第一个是管理连接(dial和hangup);第二个是数据传输(send和recv),这两个职责应该被分开。
2.开放封闭原则
简称OCP(Open Closed Principle)原则,软件实体(模块、类、函数等等)应该对扩展是开放的,对修改是关闭的,尽量通过扩展软件实体来解决需求变化,而不是通过修改已有的代码来完成变化。
- 对扩展是开放的,意味着软件实体的行为是可扩展的,当需求变更的时候,可以对模块进行扩展,使其满足需求变更的要求。
两者结合起来表述为:添加一个新的功能应该是,在已有代码基础上扩展代码(新增模块、类、方法等),而非修改已有代码(修改模块、类、方法等)。
3.里氏替换原则
子类能够替换父类,出现在父类能够出现的任何地方,子类必须完全实现父类的方法。因为继承带来的侵入性,增加了耦合性,也降低了代码灵活性,父类修改代码,子类也会受到影响,此时就需要里氏替换原则。如果子类不能完整地实现父类的方法,或者父类的某些方法在子类中已经发生“畸变”,则建议断开父子继承关系 采用依赖、聚合、组合等关系代替继承。
好处是,增强程序的健壮性,即使增加了子类,原有的子类还可以继续运行。
4.接口隔离原则
简称ISP(Interface Segregation Principle)原则,模块间要通过具体接口分离开,而不是通过类强耦合。客户端不应该依赖它不需要的接口,类间的依赖关系应该建立在最小的接口上。
在设计微服务或者类库接口的时候,如果部分接口只被部分调用者使用,那我们就需要将这部分接口隔离出来,单独给对应的调用者使用,而不是强迫其他调用者也依赖这部分不会被用到的接口。虽然接口应该被尽量细化,但是要有限度。对接口进行细化可以提高程序设计灵活性,但是如果过小,则会造成接口数量过多,使设计复杂化。所以一定要适度提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情为依赖接口的类定制服务。只暴露给调用的类它需要的方法,它不需要的方法则隐藏起来。只有专注地为一个模块提供定制服务,才能建立最小的依赖关系。
5.依赖倒置原则
简称DIP(Dependency Inversion Principle)原则,具体依赖抽象,上层不依赖下层,核心思想是面向接口编程。高层模块不依赖低层模块,它们共同依赖同一个抽象,这个抽象接口通常是由高层模块定义,低层模块实现。同时抽象不要依赖具体实现细节,具体实现细节依赖抽象。高层模块就是调用端,低层模块就是具体实现类,抽象就是指接口或抽象类,细节就是实现类。
依赖倒置的好处在小型项目中很难体现出来。但在大中型项目中可以减少需求变化引起的工作量。使并行开发更友好。
6.合成复用原则
简称CRP(Composite Reuse Principle)原则,又叫组合/聚合复用原则。它要求在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。如果要使用继承关系,则必须严格遵循里氏替换原则。合成复用原则同里氏替换原则相辅相成的,两者都是开闭原则的具体实现规范。
采用组合或聚合复用时,可以将已有对象纳入新对象中,使之成为新对象的一部分,新对象可以调用已有对象的功能,它有以下优点:
- 它维持了类的封装性。因为成分对象的内部细节是新对象看不见的,所以这种复用又称为“黑箱”复用;
- 新旧类之间的耦合度低。这种复用所需的依赖较少,新对象存取成分对象的唯一方法是通过成分对象的接口;
- 复用的灵活性高。这种复用可以在运行时动态进行,新对象可以动态地引用与成分对象类型相同的对象。
7.迪米特法则
简称LoD(Law of Demeter)法则,又叫做最少知识原则,也就是说,一个对象应当对其他对象尽可能少的了解。初衷在于降低类之间的耦合:由于每个类尽量减少对其他类的依赖,因此,很容易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系。
迪米特法则不希望类之间建立直接的联系。如果真的有需要建立联系,也希望能通过它的友元类来转达。因此,应用迪米特法则有可能造成的一个后果就是:系统中存在大量的中介类,这些类之所以存在完全是为了传递类之间的相互调用关系——这在一定程度上增加了系统的复杂度。
三、可能的面试题
1. 面向对象和面向过程的区别是什么/h2>
答:面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
PS:由此可能提到面向对象的好处(优势):
1.易维护
采用面向对象思想设计的结构,可读性高,由于继承的存在,即使改变需求,那么维护也只是在局部模块,所以维护起来是非常方便和较低成本的。
2.质量高
在设计时,可重用现有的,在以前的项目的领域中已被测试过的类使系统满足业务需求并具有较高的质量。
3.效率高
在软件开发时,根据设计的需要对现实世界的事物进行抽象,产生类。使用这样的方法解决问题,接近于日常生活和自然的思考方式,势必提高软件开发的效率和质量。
4.易扩展
由于继承、封装、多态的特性,自然设计出高内聚、低耦合的系统结构,使得系统更灵活、更容易扩展,而且成本较低。
2. 面向对象的特征有哪些/h2>
答:封装、继承、多态
PS:根据上述内容或者自己的理解在稍微展开叙述
3. 什么是多态机制ava语言如何实现多态的/h2>
答:多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。
Java实现多态有三个必要条件:继承、重写、向上转型。
继承:在多态中必须存在有继承关系的子类和父类。
重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。
只有满足了上述三个条件,我们才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而达到执行不同的行为。
4. 讲讲重写和重载的区别载的方法能否根据返回类型区分/h2>
答:方法重写是存在子父类之间的,子类定义的方法与父类中的方法具有相同的方法名字,相同的参数表和相同的返回类型;方法重载是指同一个类中的多个方法具有相同的名字,但这些方法具有不同的参数列表,即参数的数量或参数类型不能完全相同。
注: (1) 子类中不能重写父类中的final方法
(2) 子类中必须重写父类中的abstract方法
重写,父类与子类之间的多态性,对父类的函数进行重新定义。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding),子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。方法重写又称方法覆盖;
若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。并且子类函数的访问修饰权限不能少于父类的。
重载,是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时存在,具有不同的参数个数/类型。重载Overloading是一个类中多态性的一种表现。
方法重载调用方法时通过传递给它们的不同参数个数和参数类型来决定具体使用哪个方法,这就是多态性。重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同也可以不相同。无法以返回型别作为重载函数的区分标准。
5. 构造器能否被重写/h2>
答:首先构造器是用来生成一个类的实例是用来初始化这个实例用的,构造器不是方法,那么用来修饰方法特性的所有修饰符都不能用来修饰构造器(并不等与构造器具备这些特性,虽然不能用static修饰构造器,但它却有静态特性)构造器只能用 public private protected这三个权限修饰符,且不能有返回语句,所以构造器不能被重写。
注:Java在构造实例时的顺序是这样的:
1.分配对象空间,并将对象中成员初始化为0或者空,java不允许用户操纵一个不定值的对象
2.执行属性值的显式初始化
3. 执行构造器
4 .将变量关联到堆中的对象上
而执行构造器的步骤有可以分为以下几步:
1) Bind构造器的参数
2) 如果显式的调用了this,那就递归调用this构造器然后跳到步骤5
3) 递归调用显式或者隐式的父类构造器,除了Object以外,因为它没有父类
4) 执行显式的实例变量初始化
6.面向对象的五大基本原则是什么/h2>
答:SOLID原则(单一、开闭、里氏替换、接口隔离、依赖倒置),按上述解一下分别是什么,然后有的没有指定问五大原则的时候就上述七个原则吧
7.抽象类和接口有什么区别/h2>
答:抽象类和接口的区别为:表示内容不同、性质不同、成员变量不同。
内容不同:抽象类表示该类中可能已经有一些方法的具体定义;接口就仅仅只能定义各个方法的界面(方法名,参数列表,返回类型),并不关心具体细节
性质不同:抽象类是对象的抽象,接口是一种行为规范;
成员变量不同:抽象类中的成员变量可以被不同的修饰符来修饰;接口中的成员变量默认的都是静态常量(static final)。
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!