文章目录
前言
本文主要介绍面向对象编程的主要概念以及面向对象设计原则。
一、面向对象编程
在进行开发的时候经常会提到面向对象,在面向对象的世界引入了对象的概念,对象既有属性又有对应的过程,这里的属性通常就是指我们的数据成员,过程就是指我们的成员函数,函数的作用就是处理属性。
在Python开发中一切皆对象。每个类的实例或变量都有对应的内存地址,对象就是类的实例。
1、理解面向对象
1.1 对象
对象可以描述为:
- 表示所开发的应用程序内的实体。
- 实体之间可以通过交互来解决现实世界的问题。
- 例如:Car就属于一个实体,Person也是一个实体。程序员(Person) 可以驾驶 Car 从家到公司,就属于实体之间相互交互,来解决一个问题。
1.2 类
类是用来表示现实世界实体的一种方式,具有以下特点:
- 类可以定义对象的行为和属性。属性属于数据成员,行为属于成员函数(方法)。
- 类包含构造函数,这些函数的作用是为对象提供初始状态。
- 类易于复用。
- 例如:Person对象可以有name, age属性, 同时还可以提供成员函数 dive_the_car(),用来定义驾驶汽车的功能。
1.3 方法
方法定义了对象的行为,具体特点可以描述为一下几点:
- 方法就是对象的具体行为。
- 方法可以对属性进行处理,从而实现所需的功能。
在Python3中创建类和对象的例子(以 Person 为例):
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def eat_apple(self):
return f'{self.name}已经{self.age}岁了, 他可以吃苹果了'
2、面向对象编程的主要概念
面向对象编程的主要的特性相信很多人都是耳熟能详的:封装、多态、继承、抽象、组合。有些时候有的地方介绍面向对象特性的时候还会有组合的概念。
2.1 封装
封装的特点如下:
- 对象的行为对于外部空间来说是不可见的,或者说对象内部的状态是私有的,外部是不可访问的。
- 不能通过直接操作来改变对象的内部状态。但是可以通过请求来改变对应的内部状态信息,通过对应的请求类型,来调用特定的成员函数(get 或 set)来改变内部状态。
- Python中的封装不是隐式的,不像Java提供了封装所需的关键字(public、private、protected)。但是通过在变量和函数名前面添加 __前缀,就可以将其访问变为私有(相信大家都懂的 ^ _ ^)。
2.2 多态
多态的特点如下:
- 方法根据对象传入参数的不同提供不同的实现。
- 不同类型的对象可以使用相同的方法。
Python中的多态,可以说是内置的功能,用最常见的 ‘+’ 运算符来说,当 ‘+’ 作用于两个正数可以进行加法运算,但是作用于两个字符串对象就是对两个字符串进行拼接。
# 简单的demo, 直观的感受下
demo_int1 = 1
demo_int2 = 2
result_int = demo_int1 + demo_int2 # 3
demo_str1 = 'hello '
demo_str2 = 'xxxx'
result_str = demo_str1 + demo_str2 # hello xxxx
2.3 继承
继承是面向对象对象编程中经常要用的,在我曾经重构的项目中,公司建模搞出来的继承曾将我按在地上狠狠摩擦 (ㄒoㄒ)。
- 继承表示一个类可以继承父类的大部分功能
- 继承被描述为一个重用基类中的功能,并对原始的基类进行独立扩展的选项。
- 继承可以利用不同对象之间的关系建立层次结构。
- 在Python中支持多继承。
# 简单的一个继承的Demo
class A(object):
def a(self):
print('a')
class B(A):
def b(self):
print('b')
2.4 抽象
抽象的主要特征如下:
- 提供简单的客户端接口,可以通过该接口与类对象进行交互,并且调用该接口中的各个方法。
- 可以将内部类抽象为一个接口,保护内部实现
2.5 组合
组合就是指:
- 将对象或类组合成更复杂的数据结构或软件实现的方法。
- 对象可以调用其他模型中的成员函数;无需通过继承就可以实现基本的跨模块使用。
3、面向对象设计原则
3.1 开放/封闭原则
开放/封闭原则规定,类或对象及其方法对于扩展来说是开放的,但是对于修改来说,应该是封闭的。在开发时使用通用的方式来编写类或模块,以便需要扩展类或对象行为的时候不必修改类本身。
开放封闭原则的优点:
- 现有的类不会被修改,因此退化的可能性较小。
- 它还会有助于保持以前代码的向后兼容。
3.2 控制反转原则
控制反转原则是指,高层级的模块不应该依赖于底层级的模块,他们都应该依赖于抽象。细节应该依赖于抽象,而不是抽象依赖于细节。该原则建议任何两个模块之间不应以紧密方式相互依赖。基本模块和从属模块应当在他们之间提供一个抽象层来耦合。
控制反转的原则优点如下:
- 消除了模块间的紧耦合,因此消除了系统中的复杂性/刚性。
- 由于在依赖模块之间有一个明确的抽象层,因此便于通过更好的方式处理模块之间的依赖关系。
3.3 接口隔离原则
接口隔离原则规定,客户端不应该依赖于他们不需要使用的接口。
接口隔离原则的优点如下:
- 强制开发人员编写 '瘦身型’接口,并使方法与接口紧密相关。
- 防止向接口中随意添加方法。
3.4 单一职责原则
单一职责原则要求:类的职责单一,引起类变化的原因单一。
在开发中一个类应该是提供特定的功能服务。如果一个类实现了两个不同的功能,最好进行拆分。
单一职责的优点:
- 当一个功能发生变化时,除了特定的类需要改变外,其他类无需变动。
- 如果一个类有多种功能,那么依赖它的类必定会由于多种原因而经历多次修改,这种应该是避免的。
3.5 替换原则
替换原则讲的是:派生类必须能够完全取代基类。派生类必须扩展基类,并且派生类应该尽可能的对基类封闭,可以无需修改任何代码去替换基类。