问题场景

小王是某游戏公司的新入职的职员,有一天,组长交给了他一个任务,为一个即将准开发的一款游戏设计一些人物角色,其中包括多种职业,如牧师、战士和法师等等。每种职业都有一些自身独有的属性和技能,但是也会有一些共有的属性和方法。假设这家公司是用 Python 来开发游戏的。

经历过面向对象编程学习的小王很快就理清了思路,这需要用类的思想来进行设计。由于这些职业都会有一些共有的属性和方法,显然应该把这些职业的共有属性和方法拿出来作为一个公共的类,而这个公共的类就叫做基类,或者称为父类;其它职业可以基于这个公共的类来进行增加属性和方法,这些职业的类就叫做子类。这就是面向对象编码中的继承的思想,理清了设计思路之后,小王立马开始动手来实现相应的代码。


父类设计

首先,对于每一个游戏角色,它都会有姓名和性别属性。组长又告诉小王,我们不能让其它人知道我们的角色是怎么设计的,以及都有哪些属性,这又该如何设计呢?聪明的小王立马就想到了封装的思想,通过隐藏对象的属性和实现细节可以防止外部的类直接调用属性或者修改属性。所以小王立马写出了如下的代码:

class Roler(object):
"""
用户角色类,需要隐藏属性
Args:
__username: 用户名,string
__sex:性别, string
"""
def __init__(self, name=None, sex="male"):
self.__username = name
self.__sex = sex
self.__hp = 1000 def get_username(self):
# 获取用户名
return self.__username def get_sex(self):
# 获取用户性别
return self.__sex def add_hp(self, hpr):
# 角色可以回血
self.__hp += hpr def __repr__(self):
# 打印对象信息
return "username : {0}\nsex : {1}\nhp : {2}".format(self.__username, self.__sex, self.__hp)

不同于 JavaC++ ,在 Python 中是没有 private 等关键字的。所以我们如何来定义一个类的属性是私有的呢?方法就是在类属性的名字前加上两个下划线,即表示成 __username 的形式,这就是私有属性的定义方式了。其原因是因为 Python 的类的内部,所有双下划线的开始的名字都会被替换成增加单下划线和类名的方式。实质上,__username 就被替换成了 _Roler__username 的形式了。

role1 = Roler("weisheng", "male") # 建立一个新角色
print(role1) # 打印该角色的信息,调用 __repr__() 方法 print(role1.__username) # AttributeError,该属性是私有的
print(role1._Roler__username) # weisheng,可以打印

子类设计

有了父类还不够,由于每个职业都会有一些自身特有的属性和方法。所以,对于每个职业,我们也需要实现一个类。小王首先针对牧师这个职业来实现,牧师作为一个法系医疗职业,首先肯定需要一个 MP 值。同时,它能给其它用户恢复生命值。因此,可以按照如下方式来实现牧师类:

class Pastor(Roler):
"""
牧师类,继承自用户角色类
Args:
__MP: 魔法值
"""
def __init__(self, name, sex):
# 调用父类的构造函数
super().__init__(name, sex)
self.__mp = 100
def get_mp(self):
return self.__mp
def __repr__(self):
return super().__repr__() + "\nmp : {0}".format(self.__mp) def fullhealth(self, other):
# 技能1:回复其它用户生命值
other.add_hp(200)

在定义的牧师类中,首先调用父类的构造函数来对用户姓名、性别、hp值进行初始化。同时,牧师还有个mp值,这个属性是该职业独有的(请勿追究细节)。由于增加了相应的属性,所以 __repr__() 方法也需要重写,可以通过调用父类的 __repr__() 方法再加上牧师类独有的属性。

子类不能直接调用父类的私有属性,所以针对父类的一些私有属性,需要通过方法来调用。

牧师还有一个技能,他能给其它的用户角色回血,所以需要实习一个 fullhealth() 方法,参数是其它的角色类。测试用例如下:

pastor1 = Pastor("ergouzi", "male") # 建立一个牧师职业
print(pastor1) # 打印该职业角色的信息 pastor1.fullhealth(role1) # 牧师可以给其他角色回血
print(role1) # 可以发现该用户的 hp 值发生变化

其他职业的设计可以参照该职业的特点来做出相应的设计,这里就不在多做说明了。


面向对象总结

通过跟随小王的游戏角色设计,相信你已经对 Python 中的面向对象编程有了一定的了解了。面向对象编程是现在常用的一种编程方式,它是相对于面向过程编程来说的。面向对象编程把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。该思想最主要的三个特点就是封装、继承和多态,其实这些特点在上述的实例中都有体现,你能发现吗?

虽然上述的例子已经阐述了面向对象编程的大部分思想,但是本人也是第一次去进行这些类间关系的设计,所以每个例子都是非常简单的,可能在思想设计上也存在问题,请见谅。

全部代码请访问:面向对象编程

更多精彩内容将发布在公众号 冰咖啡与狗 ,或搜索微信号 icedcoffee7 添加公众号。

Python面向对象知多少?的更多相关文章

  1. Python 面向对象编程——访问限制

    <无访问限制的对象> 在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑.但是,从前面Student类的定义来看(见:Py ...

  2. Python面向对象之:三大特性:继承,封装,多态以及类的约束

    前言: python面向对象的三大特性:继承,封装,多态. 1. 封装: 把很多数据封装到⼀个对象中. 把固定功能的代码封装到⼀个代码块, 函数, 对象, 打包成模块. 这都属于封装的思想. 具体的情 ...

  3. python 面向对象初级篇

    Python 面向对象(初级篇) 概述 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发" ...

  4. Python 面向对象 基础

    编程范式概述:面向过程 和 面向对象 以及函数式编程 面向过程:(Procedure Oriented)是一种以事件为中心的编程思想. 就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现 ...

  5. python面向对象进阶(八)

    上一篇<Python 面向对象初级(七)>文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使 ...

  6. python 面向对象(进阶篇)

    上一篇<Python 面向对象(初级篇)>文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使 ...

  7. python 面向对象编程学习

    1. 问题:将所有代码放入一个py文件:无法维护 方案:如果将代码才分放到多个py文件,好处: 1. 同一个名字的变量互相不影响 2.易于维护 3.引用模块: import module 2.包:解决 ...

  8. Python面向对象详解

    Python面向对象的"怜人之处" Python的待客之道--谁能进来 Python的封装--只给你想要的 Python的继承--到处认干爹 Python的多态--说是就是

  9. python 面向对象和类成员和异常处理

    python 面向对象 你把自己想象成一个上帝,你要创造一个星球,首先你要把它揉成一个个球,两个直径就能创造一个球 class star: '''名字(name),赤道直径(equatorial di ...

随机推荐

  1. Python标准库(3.x): itertools库扫盲

    itertools functions accumulate() compress() groupby() starmap() chain() count() islice() takewhile() ...

  2. GIS基础软件及操作(五)

    原文 GIS基础软件及操作(五) 练习五.空间分析的基本操作 空间分析的基本操作 空间分析模块 空间分析是基于地理对象的位置和形态的空间数据的分析技术,其目的在于提取和传输空间信息.空间分析是地理信息 ...

  3. javascript的强制类型转换

    1.toString (1)调用toString方法 Array是将数组中的每个元素字符串化,并使用逗号拼接起来 object返回的是内部属性[[Class]]的值,[object Object] n ...

  4. WPF应用App.Config文件的保存路径

    App.Config文件有更改后,自动会保存到以下路径: C:\Users\你的系统用户名\AppData\Local\你的应用名\

  5. Android零基础入门第23节:ImageButton和ZoomButton使用大全

    原文:Android零基础入门第23节:ImageButton和ZoomButton使用大全 上一期我们学习了ImageView的使用,那么本期来学习ImageView的两个子控件ImageButto ...

  6. Android实现dialog时候弹出软键盘dialog移位问题

    Window win = getWindow(); WindowManager.LayoutParams params = win.getAttributes(); win.setSoftInputM ...

  7. Delphi中动态调用TXMLDocument的经历

    var  vXMLDocument: TXMLDocument;begin  vXMLDocument := TXMLDocument.Create('c:/temp/temp.xml');  Cap ...

  8. 比较DirectX和OpenGL的区别(比较详细)

    OpenGL是个专业的3D程序接口,是一个功能强大,调用方便的底层3D图形库.OpenGL的前身是SGI公司为其图形工作站开发的IRIS GL.IRIS GL是一个工业标准的3D图形软件接口,功能虽然 ...

  9. C++的标准库函数默认都是操作字节,而不是字符,非常痛苦,所以引入了u16string和u32string(Linux上的wchar_t是32位的原因,utf16对unicode的支持是有缺陷的)good

    时至今日,字符串使用unicode已经是不需要理由的常识,但对一些有着悠久历史的编程语言来说,这仍然是个头痛的问题.如果抛开第三方库的支持,C++其实并不能实际有效地支持unicode,即使是utf8 ...

  10. 京东sdk商家上架接口调用问题总结

    前言: 最近在做商家发布产品,调用京东sdk,发现问题很多,而且还是在我同事的帮助下完成的,摸索中,菜鸟还请高手门多多提携才好,入正题 首先是引用jd的sdk啦,京东sdk中发布商品需要调用一个 36 ...