Python面向对象的三大特性【封装、继承、多态】
首先我们要了解面向对象程序设计三大特性:
- 封装------根据职责将属性和⽅法封装到⼀个抽象的类中 ; 增强代码的安全性
- 继承------实现代码的重⽤,相同的代码不需要重复的编写 ; 增强代码的可重用性
- 多态------不同的对象调⽤相同的⽅法,产⽣不同的执⾏结果,增加代码的灵活度 。 增强代码的可扩展性
1、封装
1.1 类的私有属性和私有⽅法:
- 私有属性就是对象不希望公开的属性 ;
- 私有⽅法就是对象不希望公开的⽅法 。
1.2 定义方式
在定义属性或⽅法时,在属性名或者⽅法名前增加两个下划线,定义的就是私有属性或方法。
# 定义Cat类 class Cat: def __init__(self,name = "小白"): # _name 为私有属性 self._name = name # _eat 为私有方法 def _eat(self): print(self._name + "吃饭") def drink(self): self._eat() print(self._name + "喝水") # 创建Cat 类 cat = Cat(); # 调用Cat 喝水的方法 cat.drink()
对于私有属性和私有方法,只能在类的内部访问,类的外部无法访问。
2、继承
继承的概念:⼦类拥有⽗类的所有⽅法和属性。
语法:
class 类名(⽗类名):
pass
# 定义Cat类 class Cat: def __init__(self, name="小白"): # _name 为私有属性 self._name = name # _eat 为私有方法 def _eat(self): print(self._name + "吃饭") def drink(self): self._eat() print(self._name + "喝水") # 创建cat的子类 class kitten(Cat): def run(self): pass kitten = kitten(); kitten.drink();
⼦类继承⾃⽗类,可以直接享受⽗类中已经封装好的⽅法,不需要再次开发 。
⼦类中应该根据职责,封装⼦类特有的属性和⽅法。
继承的传递性:
其实就是,B继承A,拥有了A的属性和方法,然后C又继承B,就拥有了B和A的所有属性和方法。
方法的重写:
当⽗类的⽅法实现不能满⾜⼦类需求时,可以对⽅法进⾏重写(override)。 重写⽗类⽅法有两种情况:
1、覆盖父类的方法
如果在开发中,⽗类的⽅法实现和⼦类的⽅法实现,完全不同 ,就可以使 ⽤覆盖的⽅式,在⼦类中重新编写⽗类的⽅法实现 。
重写之后,在运⾏时,只会调⽤⼦类中重写的⽅法,⽽不再会调⽤父类封装的方法。
# 定义Cat类 class Cat: def __init__(self, name="小白"): # _name 为私有属性 self._name = name # _eat 为私有方法 def _eat(self): print(self._name + "吃饭") def drink(self): self._eat() print(self._name + "喝水") # 创建cat的子类 class kitten(Cat): def run(self): pass # 覆盖了父类的同名方法 def drink(self,name): print(name + "喝水") kitten = kitten(); kitten.drink("小小白");
2、对⽗类⽅法进⾏扩展
如果在开发中,既要使用父类的方法,又想增加功能, 就可以使⽤扩展的⽅式 。
- 在⼦类中重写⽗类的⽅法 ;
- 在需要的位置使⽤ super().⽗类⽅法来调⽤⽗类⽅法的执⾏ ;
- 代码其他的位置针对⼦类的需求,编写⼦类特有的代码实现 。
# 定义Cat类 class Cat: def __init__(self, name="小白"): # _name 为私有属性 self._name = name # _eat 为私有方法 def _eat(self): print(self._name + "吃饭") def drink(self): self._eat() print(self._name + "喝水") # 创建cat的子类 class kitten(Cat): def run(self): pass # 对父类的 sleep 方法进行了扩展 def drink(self, name): super().drink(); print(name + "喝水") kitten = kitten(); kitten.drink("小小白");
⽗类的私有属性和私有⽅法
- ⼦类对象不能在⾃⼰的⽅法内部,直接访问⽗类的私有属性或私有⽅法;
- ⼦类对象 可以通过⽗类的公有⽅法间接访问到私有属性或私有⽅法;
- 私有属性、⽅法是对象的隐私,不对外公开,外界以及⼦类都不能直接访问。
- 私有属性、⽅法通常⽤于做⼀些内部的事情 。
object 类
- 在 Python 3 中定义类时,如果没有指定⽗类,会默认使⽤ object 作为该类的基类 —— Python 3 中定义的类都是新式类 。
- 在 Python 2 中定义类时,如果没有指定⽗类,则不会以 object 作为基类 。新式类和经典类在多继承时 —— 会影响到⽅法的搜索顺序 。
- 为了保证编写的代码能够同时在 Python 2 和 Python 3 运⾏!今后在定义类时,如果没有父类,建议统一继承自 object。
3、多态
不同的⼦类对象调⽤相同的⽗类⽅法,产⽣不同的执⾏结果
# 定义Cat类 class Cat: def __init__(self, name="小白"): # _name 为私有属性 self._name = name # _eat 为私有方法 def _eat(self): print(self._name + "吃饭") def drink(self): self._eat() print(self._name + "喝水") # 创建cat的子类 class kitten(Cat): def run(self): pass # 对父类的 sleep 方法进行了扩展 def drink(self, name): super().drink(); print(name + "喝水") class dog(Cat): def drink(self): print("我是狗") kitten = kitten(); # 调用父类的 drink 方法 kitten.drink("小小白"); dog = dog(); # 调用父类的 drink 方法 dog.drink();
4、类属性和类方法
不需要创建类的对象,通过 类名. 的⽅式就可以访问类的属性或者调用类的方法 。
1、类属性
# 定义Cat类 class Cat: # name 为类属性,通过 Cat.name 访问 name = "小黄" def __init__(self, name="小白"): # _name 为私有属性 self._name = name print(Cat.name)
2、类方法
- 用@classmethod 修饰的方法为类方法;
- 类方法的参数为 cls,在类方法内部通过 cls.类属性 或者 cls.类方法 来访问同一个类中的其他类属性和类方法;
- 类方法不需要实例化就可以调用,类方法只能访问同一个类中的类属性和类方法
# 定义Cat类 class Cat: # name 为类属性,通过 Cat.name 访问 name = "小黄" def __init__(self, name="小白"): # _name 为私有属性 self._name = name # drink 为类方法 @classmethod def drink(cls): print(cls.name + "喝水") print(Cat.name) Cat.drink()
注:在普通方法中通过 类名.类属性 或者 类名.类方法 来访问类属性和类方法
6、静态方法
如果需要在类中封装⼀个⽅法,这个⽅法既不需要访问实例属性 或者调⽤实例⽅法也不需要访问类属性或者调⽤类⽅法, 这个时候,可以把这个⽅法封装成⼀个静态⽅法。
- 用@staticmethod 修饰的方法为静态方法;
- 静态方法是独立存在的,不能访问类或者实例的任何属性和方法;
- 通过 类名.静态方法 调⽤静态⽅法 。
语法:
def 静态⽅法名():
pass
# 定义Cat类 class Cat: # drink 为类的静态方法 @staticmethod def drink(): print("喝水") Cat.drink()