目录
零、面向对象的三大特征
面向对象的三大特征与语言本身无关。这只是一种编程思想,它包含封装、继承和多态。
1、封装。把客观事物(数据和行为)封装成抽象的类。并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。就像ATM机,对于银行内部人员可以对其进行随意更改,但是对于外界用户来说,钱对于外界用户来说是不可见的,只能进行存取操作。
在Python中没有专门的修饰符去用于属性的私有,如果该属性不希望在类对象外部被访问,前面使用两个“_”即可。
2、继承。它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。可提高代码的复用性。
3、多态性。允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。
一、封装
点击如图所示的圈中的任意一个箭头可以将Car类进行封装,但是封装并不影响外界对这个类的调用,除非设置了“不希望被外界使用的的属性”(只需要对对应属性前面加两个下划线)。
我们能看到,当内部调用__price信号时,是允许调用的;但是外部调用时就会报错,他说这个信号不存在。
那怎么解决呢?如下图所示:
当外部实在是想访问内部不让访问的属性时要这样操作。首先打印黄框里的内容,这个可以看到程序输出的是Car类的所有属性和方法,包括我们定义的“show”和“start”方法。然后我们还可以看到有一个_Car__price属性,我们通过这个就可以调用类内的“不允许外部调用”的属性。调用方式如红框所示。
二、继承
继承可以提高代码的复用性。
其语法格式为:
如果一个类没有任何继承类,则默认继承object。比如在上面的时候,我们定义的Car类定义的时候没有标注任何继承的父类,因此它默认继承object父类。
Python支持多继承。
定义子类时,必须在其构造函数中调用父类的构造函数。
1、继承示例
这段程序要简单的说明一下。首先的定义了一个父类Car,父类后面有俩子类Baoma和Aodi,最后定义了两个对象baoma和aodi。父类里面包含两个属性和一个方法show,子类Baoma里面使用super函数继承了父类的两个属性,而且他还自己多了一个属性baomanum;子类Aodi也一样。然后定义完对象后,通过对象名进行操作,在第23和24行是通过对象名使用父类的方法。而25,26行则是在父类之外通过对象名调用父类和子类的属性,注意在父类里面__price是不建议外界调用的,但是如果外界非要调用的话,就得用25,26行中白色圈的格式进行调用和输出。这段代码中父类、子类和对象的关系如下图所示:
2、方法重写
如果子类对继承自父类的某个属性或方法不满意,可以在子类中对其(方法体)进行重新编写。
子类重写后的方法中可以通过super().xxx()调用父类中被重写的方法。
对象想不光输出brand和price还想输出子类的第三个属性baomanum和aodinum,因此子类需要对父类的方法进行修改,修改方法见第二和第三个红色框。18和25行的操作是调用父类中的show函数,目的是输出brand和price两个属性,而第19行和第26行的操作是调用子类中修改完毕的show方法,也就是输出baomanum和aodinum。
3、object类
此类是所有类的父类,因此所有类都有object类的属性和方法。
内置函数dir()可以查看指定对象所有属性。
上图中黄框里面的东西就是Student类从object父类里面继承过来的,它是可以随便使用的。
Object有一个__str__()方法,用于返回一个对于“对象的描述”,对应于内置函数str()经常用于print()方法,帮助我们查看对象的信息,所有我们经常会对__str__()进行重写。
重写前:
重写后:
比较重写前后的输出,我们可以看到,重写前,使用str方法输出的格式是<__main__.Student object at 9087879086>,而在重写之后呢,我们发现输出的格式和我们定义的一样了。
三、多态
如上图所示,dog和cat继承了animal,animal和person继承了object,dog、cat和person之间无继承关系。但是当我们在外面定义一个函数fun时,却可以顺利的使用dog、cat和person这三个类的eat方法。也就是说传一个对象进来,只要这个对象具备eat这个方法就可以执行函数fun,与对象是否具有继承关系无关。
上图也可以看出上述规律。不管外部函数引用的类型之间有无继承关系,只要他们都有我想要的eat方法就能输出。
这点是和其他的编程语言不太一样的,也叫作“鸭子类型”。
Python是动态语言,动态语言的多态崇尚“鸭子类型”,也就是说当看到一只鸟走路像鸭子,游泳像鸭子那么这个鸟就可以叫鸭子。在鸭子类型中,不需要关心对象是什么类型,到底是不是鸭子,只关心对象的行为(方法、属性)即可。不管继承关系。
而像Java这种是静态语言。静态语言实现多态要有三个必要条件:继承关系要明确、方法重写、父类引用指向子类对象。