OOP
封装继承多态
面向对象是一种编程范式,它将现实世界中的事物抽象为对象,对象具有属性(称为字段或属性)和行为(称为方法)。面向对象编程的设计思想是以对象为中心,通过对象之间的交互来完成程序的功能,具有灵活性和可扩展性,通过封装和继承可以更好地应对需求变化。
Java面向对象的三大特性包括:封装、继承、多态:
-
封装:封装是指将对象的属性(数据)和行为(方法)结合在一起,对外隐藏对象的内部细节,仅通过对象提供的接口与外界交互。封装的目的是增强安全性和简化编程,使得对象更加独立。
-
继承:继承是一种可以使得子类自动共享父类数据结构和方法的机制。它是代码复用的重要手段,通过继承可以建立类与类之间的层次关系,使得结构更加清晰。
-
多态:多态是指允许不同类的对象对同一消息作出响应。即同一个接口,使用不同的实例而执行不同操作。多态性可以分为编译时多态(重载)和运行时多态(重写)。它使得程序具有良好的灵活性和扩展性。
多态解决了什么问题?
多态是指子类可以替换父类,在实际的代码运行过程中,调用子类的方法实现。多态这种特性也需要编程语言提供特殊的语法机制来实现,比如继承、接口类。
多态可以提高代码的扩展性和复用性,是很多设计模式、设计原则、编程技巧的代码实现基础。比如策略模式、基于接口而非实现编程、依赖倒置原则、里式替换原则、利用多态去掉冗长的 if-else 语句等等
面向对象的设计原则你知道有哪些吗
面向对象编程中的六大原则:
-
单一职责原则(SRP):一个类应该只有一个引起它变化的原因,即一个类应该只负责一项职责。例子:考虑一个员工类,它应该只负责管理员工信息,而不应负责其他无关工作。
-
开放封闭原则(OCP):软件实体应该对扩展开放,对修改封闭。例子:通过制定接口来实现这一原则,比如定义一个图形类,然后让不同类型的图形继承这个类,而不需要修改图形类本身。
-
里氏替换原则(LSP):子类对象应该能够替换掉所有父类对象。例子:一个正方形是一个矩形,但如果修改一个矩形的高度和宽度时,正方形的行为应该如何改变就是一个违反里氏替换原则的例子。
-
接口隔离原则(ISP):客户端不应该依赖那些它不需要的接口,即接口应该小而专。例子:通过接口抽象层来实现底层和高层模块之间的解耦,比如使用依赖注入。
-
依赖倒置原则(DIP):高层模块不应该依赖低层模块,二者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象。例子:如果一个公司类包含部门类,应该考虑使用合成/聚合关系,而不是将公司类继承自部门类。
-
迪米特原则 (Law of Demeter):一个对象应当对其他对象有最少的了解,只与其直接的朋友交互。
通俗易懂的例子:
- 单一职责原则(SRP):
- 例子:假设有一个
钱包类,它负责存储现金和信用卡信息。根据SRP,钱包类应该只负责存储功能,而不应该负责支付功能。如果钱包类同时负责支付,那么当支付方式发生变化时,可能会影响到钱包的存储功能,这就违反了单一职责原则。
- 例子:假设有一个
- 开放封闭原则(OCP):
- 例子:想象一个
动物园类,它可以添加新动物。根据OCP,当动物园需要添加新种类的动物时,我们不需要修改动物园类本身,而是通过扩展(如添加新的动物类)来实现。例如,如果动物园要引入企鹅,我们创建一个企鹅类,而不需要更改动物园类的代码。
- 例子:想象一个
- 里氏替换原则(LSP):
- 例子:如前所述,
交通工具类有移动方法,自行车和汽车是其子类。根据LSP,自行车和汽车都应该能够替换交通工具对象,而不影响程序的正确性。如果汽车类需要燃料才能移动,那么它可能违反了LSP,因为不是所有交通工具都需要燃料。
- 例子:如前所述,
- 接口隔离原则(ISP):
- 例子:假设有一个
电器接口,它有开关和调节温度的方法。根据ISP,如果一个电风扇不需要调节温度,那么它不应该依赖于包含调节温度方法的电器接口。相反,电风扇应该依赖于一个只包含开关方法的更小的接口。
- 例子:假设有一个
- 依赖倒置原则(DIP):
- 例子:假设有一个
餐厅类,它依赖于厨师类来准备食物。根据DIP,餐厅类不应该直接依赖于具体的厨师类实现,而是依赖于一个抽象的厨师接口。这样,如果需要更换不同类型的厨师,比如从法国厨师更换为意大利厨师,餐厅类不需要做任何修改。
- 例子:假设有一个
- 迪米特原则(LoD):
- 例子:假设有一个
学生类,它需要获取课程信息。根据LoD,学生类不应该直接与课程类交互,如果需要获取课程信息,应该通过课程表类来实现,因为课程表是学生的直接朋友,而课程不是。
- 例子:假设有一个
通过这些例子,我们可以看到SOLID原则是如何帮助我们设计出更加灵活、可维护和可扩展的软件系统的。
重载与重写有什么区别?
- 重载(Overloading)指的是在同一个类中,可以有多个同名方法,它们具有不同的参数列表(参数类型、参数个数或参数顺序不同),编译器根据调用时的参数类型来决定调用哪个方法。
- 重写(Overriding)指的是子类可以重新定义父类中的方法,方法名、参数列表和返回类型必须与父类中的方法一致,通过@override注解来明确表示这是对父类方法的重写。
重载是指在同一个类中定义多个同名方法,而重写是指子类重新定义父类中的方法。
Java抽象类和接口的区别是什么?
两者的特点:
- 抽象类用于描述类的共同特性和行为,可以有成员变量、构造方法和具体方法。适用于有明显继承关系的场景。
- 接口用于定义行为规范,可以多实现,只能有常量和抽象方法(Java 8 以后可以有默认方法和静态方法)。适用于定义类的能力或功能。
两者的区别:
- 实现方式:实现接口的关键字为implements,继承抽象类的关键字为extends。一个类可以实现多个接口,但一个类只能继承一个抽象类。所以,使用接口可以间接地实现多重继承。
- 方法方式:接口只有定义,不能有方法的实现,java 1.8中可以定义default方法体,而抽象类可以有定义与实现,方法可在抽象类中实现。
- 访问修饰符:接口成员变量默认为public static final,必须赋初值,不能被修改;其所有的成员方法都是public、abstract的。抽象类中成员变量默认default,可在子类中被重新定义,也可被重新赋值;抽象方法被abstract修饰,不能被private、static、synchronized和native等修饰,必须以分号结尾,不带花括号。
- 变量:抽象类可以包含实例变量和静态变量,而接口只能包含常量(即静态常量)。
总结
怎么说呢,其实不难,只要肯下功夫多实践,在日常学习中多留意这些字段,修饰符,各种方法,总能领略七七八八。
以上。