面向对象编程介绍
面向对象(object-oriented ;简称: OO) 至今还没有统一的概念,我这里把它定义为: 按人们认识客观世界的系统思维方式,采用基于对象(实体)的概念建立模型,模拟客观世界分析、设计、实现软件的办法。
面向对象编程(Object Oriented Programming-OOP) 是一种解决软件复用的设计和编程方法。这种方法把软件系统中相近相似的操作逻辑和操作应用数据、状态,以类的型式描述出来,以对象实例的形式在软件系统中复用,以达到提高软件开发效率的作用。
类和对象
面向对象编程的2个非常重要的概念:类和对象。
- 对象是面向对象编程的核心,在使用对象的过程中,为了将具有共同特征和行为的一组对象抽象定义,提出了另外一个新的概念——类。
- 类就相当于制造飞机时的图纸,用它来进行创建的飞机就相当于对象。
类
具有相似内部状态和运动规律的实体的集合(或统称为抽象)。具有相同属性和行为事物的统称。类是抽象的,在使用的时候通常会找到这个类的一个具体的存在,使用这个具体的存在。一个类可以找到多个对象。
对象
某一个具体事物的存在 ,在现实世界中可以是看得见摸得着的,可以是直接使用的。
类和对象之间的关系
类就是创建对象的模板。
类的构成
类(Class) 由3个部分构成:
- 类的名称:类名
- 类的属性:一组数据
- 类的方法:允许对进行操作的方法 (行为)
示例:狗类
- 类名:狗(Dog)
- 属性:品种 、毛色、性别、名字、 腿儿的数量
- 方法(行为/功能):叫 、跑、咬人、吃、摇尾巴
类的抽象
拥有相同(或者类似)属性和行为的对象都可以抽像出一个类。
定义类
定义一个类,格式如下:
class 类名:
方法列表
示例:定义一个Car类
# 定义类
class Car:
# 方法
def getCarInfo(self):
print('车轮子个数:%d, 颜色%s'%(self.wheelNum, self.color))
def move(self):
print("车正在移动...")
说明:
- 定义类时有2种:新式类和经典类,上面的Car为经典类,如果是Car(object)则为新式类;
- 类名的命名规则按照"大驼峰"。
创建对象
python中,可以根据已经定义的类去创建出一个个对象。
创建对象的格式为:
对象名 = 类名()
创建对象的示例:
# 定义类
class Car:
# 移动
def move(self):
print('车在奔跑...')
# 鸣笛
def toot(self):
print("车在鸣笛...嘟嘟..")
# 创建一个对象,并用变量BMW来保存它的引用
BMW = Car()
BMW.color = '黑色'
BMW.wheelNum = 4 #轮子数量
BMW.move()
BMW.toot()
print(BMW.color)
print(BMW.wheelNum)
总结:
- BMW = Car(),这样就产生了一个Car的实例对象,此时也可以通过实例对象BMW来访问属性或者方法;
- 第一次使用BMW.color = '黑色'表示给BMW这个对象添加属性,如果后面再次出现BMW.color = xxx表示对属性进行修改;
- BMW是一个对象,它拥有属性(数据)和方法(函数);
- 当创建一个对象时,就是用一个模子,来制造一个实物 。
__ init __()方法
我们已经给BMW这个对象添加了2个属性,wheelNum(车的轮胎数量)以及color(车的颜色),试想如果再次创建一个对象的话,肯定也需要进行添加属性,显然这样做很费事,那么有没有办法能够在创建对象的时候,就顺便把车这个对象的属性给设置呢?我们可以用__ init __()方法实现这一点。
使用方式
def 类名:
#初始化函数,用来完成一些默认的设定
def __init__():
pass
__init __()方法的调用
# 定义汽车类
class Car:
def __init__(self):
self.wheelNum = 4
self.color = '蓝色'
def move(self):
print('车在跑,目标:夏威夷')
# 创建对象
BMW = Car()
print('车的颜色为:%s'%BMW.color)
print('车轮胎数量为:%d'%BMW.wheelNum)
结果:
车的颜色为:blue
车轮胎数量为:4
总结:
当创建Car对象后,在没有调用__ init__()方法的前提下,BMW就默认拥有了2个属性wheelNum和color,原因是__ init__()方法是在创建对象后,就立刻被默认调用了。
传参
既然在创建完对象后__ init__()方法已经被默认的执行了,那么能否让对象在调用__ init__()方法的时候传递一些参数呢?如果可以,那怎样传递呢?
# 定义汽车类
class Car:
def __init__(self, newWheelNum, newColor):
self.wheelNum = newWheelNum
self.color = newColor
def move(self):
print('车在跑,目标:夏威夷')
# 创建对象
BMW = Car(4, 'green')
print('车的颜色为:%s'%BMW.color)
print('车轮子数量为:%d'%BMW.wheelNum)
结果:
车的颜色为:green
车轮胎数量为:4
总结:
- __ init__()方法,在创建一个对象时默认被调用,不需要手动调用;
- __ init__(self)中,默认有1个参数名字为self,如果在创建对象时传递了2个实参,那么__init __(self)中出了self作为第一个形参外还需要2个形参,例如__init __(self,x,y);
- __ init__(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递进去。
self
理解self
如下示例:
# 定义一个类
class Animal:
# 方法
def __init__(self, name):
self.name = name
def printName(self):
print('名字为:%s'%self.name)
# 定义一个函数
def myPrint(animal):
animal.printName()
dog1 = Animal('西西')
myPrint(dog1)
dog2 = Animal('北北')
myPrint(dog2)
运行结果:
名字为:西西
名字为:北北
总结:
- 所谓的self,可以理解为自己;
- 可以把self当做Java中类里面的this指针一样理解,就是对象自身的意思;
- 某个对象调用其方法时,python解释器会把这个对象作为第一个参数传递给self,所以开发者只需要传递后面的参数即可。
举个例子:老王开枪
人类
- 属性
- 姓名
- 血量
- 持有的枪
- 方法
- 安子弹
- 安弹夹
- 拿枪(持有抢)
- 开枪
子弹类
- 属性
- 杀伤力
- 方法
- 伤害敌人(让敌人掉血)
弹夹类
- 属性
- 容量(子弹存储的最大值)
- 当前保存的子弹
- 方法
- 保存子弹(安装子弹的时候)
- 弹出子弹(开枪的时候)
枪类
- 属性
- 弹夹(默认没有弹夹,需要安装)
- 方法
- 连接弹夹(保存弹夹)
- 射子弹
人类实现:
class Ren:
def __init__(self,name):
self.name = name
self.xue = 100
self.qiang = None
def __str__(self):
return self.name + "剩余血量为:" + str(self.xue)
def anzidan(self,danjia,zidan):
danjia.baocunzidan(zidan)
def andanjia(self,qiang,danjia):
qiang.lianjiedanjia(danjia)
def naqiang(self,qiang):
self.qiang = qiang
def kaiqiang(self,diren):
self.qiang.she(diren)
def diaoxue(self,shashangli):
self.xue -= shashangli
弹夹类实现:
class Danjia:
def __init__(self, rongliang):
self.rongliang = rongliang
self.rongnaList = []
def __str__(self):
return "弹夹当前的子弹数量为:" + str(len(self.rongnaList)) + "/" + str(self.rongliang)
def baocunzidan(self,zidan):
if len(self.rongnaList) < self.rongliang:
self.rongnaList.append(zidan)
def chuzidan(self):
#判断当前弹夹中是否还有子弹
if len(self.rongnaList) > 0:
#获取最后压入到单间中的子弹
zidan = self.rongnaList[-1]
self.rongnaList.pop()
return zidan
else:
return None
子弹类实现:
class Zidan:
def __init__(self,shashangli):
self.shashangli = shashangli
def shanghai(self,diren):
diren.diaoxue(self.shashangli)
枪类实现:
class Qiang:
def __init__(self):
self.danjia = None
def __str__(self):
if self.danjia:
return "枪当前有弹夹"
else:
return "枪没有弹夹"
def lianjiedanjia(self,danjia):
if not self.danjia:
self.danjia = danjia
def she(self,diren):
zidan = self.danjia.chuzidan()
if zidan:
zidan.shanghai(diren)
else:
print("没有子弹了,放了空枪....")
调用运行:
#创建一个人对象
laowang = Ren("老王")
#创建一个弹夹
danjia = Danjia(20)
print(danjia)
#循环的方式创建一颗子弹,然后让老王把这颗子弹压入到弹夹中
i=0
while i<5:
zidan = Zidan(5)
laowang.anzidan(danjia,zidan)
i+=1
#测试一下,安装完子弹后,弹夹中的信息
print(danjia)
#创建一个枪对象
qiang = Qiang()
print(qiang)
#让老王,把弹夹连接到枪中
laowang.andanjia(qiang,danjia)
print(qiang)
#创建一个敌人
diren = Ren("敌人")
print(diren)
#让老王拿起枪
laowang.naqiang(qiang)
#老王开枪射敌人
laowang.kaiqiang(diren)
print(diren)
print(danjia)