理解面面向对象

两种编程思想

面向过程

{callout color=”#f0ad4e”}
面向过程思考的重点在于步骤
{/callout}

  • 我们解决问题的时候,会把所需要的步骤都列出来,然后按照步骤写代码挨个实现,这种过程化的叙事思维,就是面向过程思想

  • 比如文件操作的基本步骤 1.打开文件 2.向文件中写入内容 3.关闭文件. 我们的代码就是按照这个步骤写的, 这就是典型的面向过程编程思维. 这里强调的是步骤.

  • 再举个著名的例子: 把大象装冰箱需要几步. 第一步,把冰箱门打开,第二步,把大象推进去,第三步,把冰箱门关闭. 这也是典型的面向过程强调的是步骤.

面向对象

{callout color=”#f0ad4e”}
面向对象更讲事情的对象
{/callout}

  • 按照步骤写代码固然可行, 但是把大象放到冰箱里换成把大象放到衣柜里,把鲨鱼放到冰箱里,把鲨鱼放到衣柜里等等, 这里类似的步骤用面向过程编码的话就要重复的一遍遍的去写. 这样就导致代码开发变成了记流水账,久而久之代码就会有大量的重复这是我们不想看到的.

  • 那么当我们的视角不再是步骤过程,而是操作对象(这里对象可以理解为冰箱,衣柜,大象,鲨鱼)的时候,我们可以发现冰箱,衣柜,大象,鲨鱼都有相同的特点. 冰箱,衣柜都具有打开和关闭这两个方法的储物空间,大象,鲨鱼都是动物. 按照这样的想法我们可以把这件事简化成:储物空间门打开,动物走进去,储物空间门关闭. 那么类似大象放到冰箱里这样的问题就被我们分解成了储物空间和动物两个对象, 然后再分别描述这两个对象的行为(这里的行为可以理解为储物空间的打开和关闭, 动物被放到储物空间中).

  • 这种把问题分解成各个对象,描述对象在整个事情中的行为,就是面向对象思想.

  • 面向过程更讲事情的步骤,面向对象更讲事情的对象. 面向对象可以基于对象的共性做提炼,为软件工程的复用和扩展打好了坚实的基础. 这也是为什么在很多大型软件开发选型上,大多会使用面向对象编程.

面向对象三大特性

1. 封装

  • 封装就是隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别,将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。

  • 封装的目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口,以特定的访问权限来使用类的成员。

  • 面相对象的不就是使用程序处理事情时以对象为中心去分析吗,与面向过程不同,面向过程关心处理的逻辑、流程等问题,而不关心事件主体。而面向对象即面向主体,所以我们在解决问题时应该先进行对象的封装(对象是封装类的实例,比如张三是人,人是一个封装类,张三只是对象中的一个实例、一个对象)。比如我们日常生活中的小兔子、小绵羊都可以封装为一个类。

比如兔子的属性有两只耳朵、四只腿、一双眼睛、三瓣嘴等;行为(功能)有跑、跳、吃素等。

2. 继承

  • 继承是面向对象的基本特征之一,继承机制允许创建分等级层次的类。 继承就是子类继承父类的特征和行为 ,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。

3. 多态

  • 多态同一个行为具有多个不同表现形式或形态的能力。是指一个类实例(对象)的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。

多态的优点:

  • 消除类型之间的耦合关系
  • 可替换性
  • 可扩充性
  • 接口性
  • 灵活性
  • 简化性

类和对象

初识类
1
2
3
4
5
6
7
8
class Box:
def print_box(self):
print(self.height)
print(self.width)
x = Box()
x.height = 60
x.width = 50
x.print_box()
类和实例的应用
①烤地瓜
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class SweetPotato:
def __init__(self):
# 被烤的时间
self.cook_time = 0
# 地瓜的状态
self.cook_static = '生的'
# 调料列表
self.condiments = []
def cook(self, time):
self.cook_time += time
if 0 <= self.cook_time < 3:
self.cook_static = '生的'
elif 3 <= self.cook_time < 5:
self.cook_static = '半熟的'
elif 5 <= self.cook_time < 10:
self.cook_static = '半熟的'
else:
self.cook_static = '糊了'
def __str__(self):
return f'烤了{self.cook_time}分钟,现在是{self.cook_static},而且放了{self.condiments}'
def add_condiments(self, name):
self.condiments.append(name)
hongshu1 = SweetPotato()
print(hongshu1)
hongshu1.cook(3)
print(hongshu1)
hongshu1.cook(5)
print(hongshu1)
hongshu1.cook(5)
print(hongshu1)
hongshu1.add_condiments('糖')
print(hongshu1)
hongshu1.add_condiments('hsi')
print(hongshu1)
②搬家
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Furniture:
def __init__(self, name, area):
self.name = name
self.area = area
class House:
def __init__(self, address, area):
self.address = address
self.area = area
self.free_area = area
self.furniture = []
def add_furniture(self, item):
if item.area < self.free_area:
self.free_area -= item.area
self.furniture.append(item.name)
else:
print('太大放不下了')
def __str__(self):
return f'这个房子在{self.address},总面积:{self.area},还有面积{self.free_area},里面有{self.furniture}'
shafa1 = Furniture('沙发', 5)
chaji1 = Furniture('茶几', 2)
home1 = House('深圳', 6)
home1.add_furniture(chaji1)
home1.add_furniture(shafa1)
print(home1)