1.面向对象两个核心的概念————类与对象
- 类:是一类具有相同特征或行为的事物的一个统称
- 对象:由类创建出来的一个具体的存在
- 类和对象的关系:先有类再有对象;类是模板 对象是根据这个模板创建出来的;类只需要有一个 对象可以有多个
2.类
-
类:是属性(这一类事务的共同信息) 和 方法(你能完成的动作)组成的一个集合
-
类名的命名(大驼峰命名法)
大驼峰命名法:
1.每个单词的首字母大写
2.单词与单词之间没有下划线 -
类名的确定
名词提炼法分析整个业务流程,出现的名词,通常就是找到的类 -
属性和方法的确定
1.属性:这个类创建出来的对象有什么特征
2.方法:这个类创建出来的对象有什么行为
对 对象的特征描述,通常可以定义成属性
对象具有的行为(动词),通常可以定义为方法
3.面向对象的三个基本特征———封装、继承、多态
3.1封装
封装:根据职责将属性和方法封装到一个抽象的类中;利用抽象数据类型和基于数据的操作结合在一起,数据被保护在抽象数据类型的内部,系统的其他部分只有通过包裹在数据之外被授权的操作,才能与这个抽象数据类型进行交互。
- 一个栗子:
需求:
1.小明和小美都爱跑步
2.小美体重45.0公斤
2.每次跑步都会减肥0.5公斤
3.每次吃东西体重都会增加1公斤
class Person:
def __init__(self,name,weight):
self.name = name
self.weight = weight
def __str__(self):
return '我的名字叫 %s 体重是 %.2f' %(self.name,self.weight)
# 在对象的方法内部 是可以直接访问对象的属性的
def run(self):
print('%s 去跑步~~~' %(self.name))
self.weight -= 0.5
def eat(self):
print('%s 去吃东西~~~' %(self.name))
self.weight += 1
xiaoming = Person('小明',75.5)
xiaoming.run()
xiaoming.eat()
print(xiaoming)
xiaomei = Person('小美',50)
xiaomei.eat()
xiaomei.run()
3.2继承
(1)继承:实现代码的重用,相同的代码通过继承而不需要重复的写;完全继承父类,并可以形成自己特有的方法与属性。一个类可以从另一个类(即它的父类)继承状态和行为。继承父类的类称为子类。
继承的优越性:通过使用继承,程序员可以在不同的子类中多次重新使用父类中的代码,使程序结构清晰,易于维护和修改,而子类又可以提供一些特殊的行为,这些特殊的行为在父类中是没有的 。
(2)重写
当父类方法不能满足子类的需求时:
a.覆盖父类方法
- 一个栗子:
class Animal:
def eat(self):
print('吃~~~')
def drink(self):
print('喝~~~')
def run(self):
print('跑~~~')
def sleep(self):
print('睡~~~')
class Cat(Animal):
def call(self):
print('喵喵')
class HelloKitty(Cat):
def sepak(self):
print('我可以说日语!!')
def call(self):
print('$#%$#%$#')
kt = HelloKitty()
kt.eat()
kt.run()
kt.call()
kt.sepak()
##运行结果:
吃~~~
跑~~~
$#%$#%$#
我可以说日语!!
从这个例子中我们可以看到Cat这个类继承了Animal类,Cat又被HelloKitty类继承,则HelloKitty这个类将继承Cat类中所有的方法及属性,并且HelloKitty类对父类Cat类的call方法进行了覆盖重写,可以从运行结果看到,当父类的方法被覆盖后,子类将不再使用父类被覆盖的的方法。
b.对父类方法进行扩展
- 一个栗子:
class Animal:
def eat(self):
print('吃~~~')
def drink(self):
print('喝~~~')
def run(self):
print('跑~~~')
def sleep(self):
print('睡~~~')
class Cat(Animal):
def call(self):
print('喵喵')
class HelloKitty(Cat):
def sepak(self):
print('我可以说日语!!')
def call(self):
# 调用原本在父类中封装的方法
super().call()
# Cat.call(self) python2.x
print('$#%$#%$#')
kt = HelloKitty()
kt.eat()
kt.run()
kt.call()
kt.sepak()
##运行结果:
吃~~~
跑~~~
喵喵
$#%$#%$#
我可以说日语!!
从这个例子的运行结果我们可以看到HelloKitty类不仅可以“喵喵”叫而且还可以说自己的语言;也就是说扩展就是在继承父类多有的方法上再添加自己特有的方法
需要注意的是:python2和python3的编译器中扩展方法使用是不同的
- 在python.3.X super().call() 调用原本在父类中封装的方法
- 在 python2.x中 Cat.call(self)
3.3多态
多态以继承与封装为前提;不同的子类对象调用相同的方法 产生不同的结果;一个程序中同名的方法共存的情况,调用者只需使用同一个方法名,系统会根据不同情况,调用相应的不同方法,从而实现不同的功能。多态性又被称为“一个名字,多个方法”。
- 一个栗子:
class Dog(object):
def __init__(self, name):
self.name = name
def game(self):
print('%s 玩得很开心~' % (self.name))
class Gaofei(Dog):
# 父类方法不能满足子类的需求 重写game
def game(self):
print('%s玩的不开心~~~' %(self.name))
class Person(object):
def __init__(self,name):
self.name = name
def game_with_dog(self,dog):
print('%s和%s玩' %(self.name,dog.name))
dog.game()
# 创建一个狗对象
wangcai2 = Dog('大黄')
wangcai = Gaofei('高飞')
# 创建一个人对象
xiaoming = Person('小明')
# 让小明和狗玩
xiaoming.game_with_dog(wangcai)
print("************************")
xiaoming.game_with_dog(wangcai2)
##运行结果:
小明和高飞玩
高飞玩的不开心~~~
************************
小明和大黄玩
大黄 玩得很开心~
从这个例子,我们可以看到Gaofei类是Dog类的子类,继承了Dog类的所有方法并封装成了一个新类;创建一个Person类的对象xiaoming,用不同的对象(wangcai和wangcai2)去调用这个对象的方法,最后出现的结果是不同的。这就是多态,多态一定是在封
装和继承的基础上实现的,否则不能称之为多态!
4.一些例题
需求一
1.士兵瑞恩有一把AK47
2.士兵可以开火(士兵开火扣动的是扳机)
3.枪 能够 发射子弹(把子弹发射出去)
4.枪 能够 装填子弹 --增加子弹的数量
实现:
class Gun:
def __init__(self,model):
self.model = model
self.bullet_count = 0
def add_bllet(self,count):
self.bullet_count += count
def shoot(self):
if self.bullet_count <= 0:
print('%s 没有子弹了...' %(self.model))
return
self.bullet_count -= 1
print('%s------%s' %(self.model,self.bullet_count))
class Soldier:
def __init__(self,name):
self.name = name
self.gun = None
def fire(self):
if self.gun == None:
print('%s 没有枪...' %(self.name))
return
self.gun.add_bllet(50)
self.gun.shoot()
ak47 = Gun('ak47')
ryan = Soldier('Ryan')
ryan.gun = ak47
ryan.fire()
ryan.fire()
需求二
1.房子有户型,总面积和家具名称列表
新房子是没有家具的
2.家具有名字和占地面积,其中
eg:占地 6平方米
3.将以上三件家具添加到房子中
4.打印房子的时候,要求输出:户型 总面积 剩余面积 家具名称列表
实现:
class HouseItem:
# 初始化方法
def __init__(self, name, area):
self.name = name
self.area = area
def __str__(self):
return '[%s] 占地 %.2f' % (self.name, self.area)
class House:
def __init__(self, house_type, area):
self.house_type = house_type
self.area = area
# 剩余面积
self.free_area = area
self.item_list = []
def __str__(self):
return '户型:%s\n总面积:%.2f[剩余:%.2f]\n家具:%s' \
% (self.house_type
, self.area, self.free_area
, self.item_list)
def add_item(self, item):
# 1.判断家具的面积
if item.area > self.free_area:
print('%s 的面积太大,无法添加' %(item.name))
return
# 要将家具的名称添加到列表中去
self.item_list.append(item.name)
# 计算剩余面积
self.free_area -= item.area
# 创建家具
bed = HouseItem('床', 400)
print(bed)
chest = HouseItem('chest', 2)
print(chest)
table = HouseItem('桌子', 4.5)
print(table)
# 创建房子对象
my_home = House('两室一厅',90)
# 将家具添加到房子里面去
my_home.add_item(bed)
my_home.add_item(chest)
my_home.add_item(table)
print(my_home)