Python面向对象编程之封装、继承与多态
一、封装
封装从字面上来理解就是包装的意思,专业点就是信息隐藏,是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系。系统的其他对象只能通过包裹在数据外面的已经授权的操作来与这个封装的对象进行交流和交互。也就是说用户是无需知道对象内部的细节,但可以通过该对象对外的提供的接口来访问该对象。
对于封装而言,一个对象它所封装的是自己的属性和方法,所以它是不需要依赖其他对象就可以完成自己的操作。使用封装有三大好处:
-
良好的封装能够减少耦合。
-
类内部的结构可以自由修改。
-
可以对成员进行更精确的控制。
-
隐藏信息,实现细节。
封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果不想被外界方法,我们大可不必提供方法给外界访问。但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了。
# 定义一个学生类,拥有name、score属性
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
def print_score(self):
print('%s: %s' % (self.__name, self.__score))
实例化
>>> test = Student('JCheung', 98)
>>> test.score
98
>>> test.score = 59
>>> test.score
59
由上可见,外部代码还是可以自由地修改实例test的name、score属性。如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。
class Student(object):
def __init__(self, name, score):
self.__name = name
self.__score = score
def print_score(self):
print('%s: %s' % (self.__name, self.__score))
改完后,对于外部代码来说,没什么变动,但是已经无法从外部访问实例变量:
>>> test = Student('JCheung',98)
>>> test.score
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
test.score
AttributeError: 'Student' object has no attribute 'score'
>>> test._score
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
test._score
AttributeError: 'Student' object has no attribute '_score'
>>>
这样就确保了外部代码不能随意修改对象内部的状态.通过访问限制的保护,代码更加健壮。
但是如果外部代码要获取name和score怎么办?可以给Student类增加get_name和get_score这样的方法:
class Student(object):
...
def get_name(self):
return self.__name
def get_score(self):
return self.__score
如果外部代码要获取修改score怎么办?可以再给Student类增加set_score方法:
class Student(object):
...
def set_score(self, score):
self.__score = score
二、继承
在面向对象编程中,当我们已经创建了一个类,而又想再创建一个与之相似的类,比如添加几个方法,或者修改原来的方法,这时我们不必从头开始,可以从原来的类派生出一个新的类,我们把原来的类称为父类或基类,而派生出的类称为子类,子类继承了父类的所有数据和方法。
让我们看一个简单的例子,首先我们定义一个 Animal 类:
class Animal(object):
def __init__(self, name):
self.name = name
def greet(self):
print 'Hello, I am %s.' % self.name
现在,我们想创建一个 Dog 类,比如:
class Dog(object):
def __init__(self, name):
self.name = name
def greet(self):
print 'WangWang.., I am %s. ' % self.name
可以看到,Dog 类和 Animal 类几乎是一样的,只是 greet 方法不一样,我们完全没必要创建一个新的类,而是从 Animal 类派生出一个新的类:
class Dog(Animal):
def greet(self):
print 'WangWang.., I am %s. ' % self.name
Dog 类是从 Animal 类继承而来的,Dog 类自动获得了 Animal 类的所有数据和方法,而且还可以对父类的方法进行修改,我们看看使用:
>>> animal = Animal('animal') # 创建 animal 实例
>>> animal.greet()
Hello, I am animal.
>>>
>>> dog = Dog('dog') # 创建 dog 实例
>>> dog.greet()
WangWang.., I am dog.
我们还可以对 Dog 类添加新的方法:
class Dog(Animal):
def greet(self):
print 'WangWang.., I am %s. ' % self.name
def run(self):
print 'I am running.I am running'
使用:
>>> dog = Dog('dog')
>>> dog.greet()
WangWang.., I am dog.
>>> dog.run()
I am running
三、多态
多态的概念其实不难理解,它是指对不同类型的变量进行相同的操作,它会根据对象(或类)类型的不同而表现出不同的行为。
事实上,我们经常用到多态的性质,比如:
>>> 1 + 2
3
>>> 'a' + 'b'
'ab'
可以看到,我们对两个整数进行 + 操作,会返回它们的和,对两个字符进行相同的 + 操作,会返回拼接后的字符串。也就是说,不同类型的对象对同一消息会作出不同的响应。
再看看类的例子:
class Animal(object):
def __init__(self, name):
self.name = name
def greet(self):
print 'Hello, I am %s.' % self.name
class Dog(Animal):
def greet(self):
print 'WangWang.., I am %s.' % self.name
class Cat(Animal):
def greet(self):
print 'MiaoMiao.., I am %s' % self.name
def hello(animal):
animal.greet()
看看多态的使用:
>>> dog = Dog('dog')
>>> hello(dog)
WangWang.., I am dog.
>>>
>>> cat = Cat('cat')
>>> hello(cat)
MiaoMiao.., I am cat
可以看到,cat 和 dog 是两个不同的对象,对它们调用 greet 方法,它们会自动调用实际类型的 greet 方法,作出不同的响应。这就是多态的魅力。
- 继承可以拿到父类的所有数据和方法,子类可以重写父类的方法,也可以新增自己特有的方法。
- 有了继承,才有了多态,不同类的对象对同一消息会作出不同的相应。
相关链接:
https://blog.csdn.net/jianyuerensheng/article/details/51602015
https://my.oschina.net/zhangyujian/blog/754344
http://funhacks.net/explore-python/Class/inheritance_and_polymorphism.html
上一篇:微信小程序之页面传值
下一篇:Python进阶之新式类与经典类