标签:Python
本文前面的内容参见:Python面向对象编程(上)
面向对象的关键概念/构建块
下面的5个主题是理解Python或任何语言中面向对象编程的关键概念。一旦理解了这些主题,它们就成为了我们可以组合和编织在一起的构建块,以创建令人惊叹且易于使用的对象。
抽象和封装
这两个OOP构建块都只关心向用户显示他们需要看到的内容,隐藏用户不需要关心的方法、函数和属性。在Python中,向用户隐藏内容的方法是在def之后使用下划线前缀,_或者__,注意,内置的__init__有双下划线前缀。单下划线表示部分隐藏,双下划线表示完全隐藏。从技术上讲,Python中不可能隐藏任何东西,但这是惯例。一些IDE将遵循此约定,不允许查看或自动完成以单下划线为前缀的任何内容。使用双下划线,用户将需要自行间接访问属性:
图2
面向对象的抽象
抽象回答了“向用户显示什么”的问题。
例如,为汽车(car)对象包含一个drive()方法是有意义的。这里的目标应该是为用户提供有帮助、有用和明显的函数、方法和属性,所以不想向用户展示内燃机的所有细节。我们不想让他们考虑当曲轴移动时每个活塞需要旋转多少,当他们只想驾驶时,将所有信息作为参数传递。这种详细程度对于对象的工作是必要的,但对于这个对象来说,需要有一些内部的东西,只有我们作为对象的开发人员才需要关心。
换句话说,细节需要被抽象掉。因此,用户可以专注于汽车对象的功能,而不必考虑其工作方式的复杂性。对于用户来说,与drive()方法交互的一种更简单、更好的方法可能是传递一个名为speed的参数,该参数指示他们希望以多快的速度行驶。有了这些输入,在内部解决细节问题。如果有些东西太深奥,考虑将其隐藏内部,以免让用户不知所措。这样,可以将细节抽象出来,只向他们展示需要看到的东西。
图3
面向对象的封装
封装回答了“如何”向用户显示属性、函数和方法的问题,目标是将操作对象所需的一切都“隐藏起来”。封装的主要方面是:
1.保护代码,用户在尝试使用代码时不犯已知错误。
2.将对象工作所需的所有部件保持在一个位置。
封装大量使用对象私有的函数、方法和属性,然后只能由对象本身内部访问。通过这种方式,这些内部细节被封装。这让用户专注于我们希望他们与对象交互的“正确”方式,并防止他们犯我们已经考虑过的错误。
图4
抽象和封装一起工作,向用户展示成功使用我们的类的最小框架。我们希望保持简单,尽量不为难用户。这也有助于编写更少的错误代码,因为限制用户与对象交互的方式限制了他们破坏对象的方式以及我们需要考虑的边缘情况。
继承与组合
这些OOP构建块与共享其他对象的行为和能力的对象相关,它们用于对象之间具有层次关系的情况。
当对象也是另一种类型的对象时使用继承,例如轿车是一种汽车。通过声明新的“子”对象也是“父”对象的类型,函数、方法和属性在对象之间共享。它可以使用父对象的类定义,也可以重写父对象在这个子对象中的工作方式。
图5
组合是指当我们的对象“有”另一个对象时,例如汽车有轮子。通过使整个对象成为另一个较大对象的简单属性,在对象之间共享函数、方法和属性。一般来说,组合更灵活,更容易重构。因此,至少应该考虑在每次要实现继承时使用组合而不是继承。想象一下这种差异,因为取下汽车的车轮比完全重新定义一辆没有车轮的汽车更容易。
图6
多态性
多态性意味着代码能够根据我们所寻找的口味和我们提供的成分,拥有不同的口味。多态性的一个完美例子是考虑Python如何实现int和str对象以同时使用 运算符。当将 与整数一起使用时,它会将它们相加,但如果将 与字符串一起使用,则会将它们连接在一起。用户只要想组合东西,就可以使用同一个操作符。然而,在不同的情况下,结果会有所不同。因此,多态性允许同一对象在不同的环境下以不同的方式进行动态反应,这减少了用户使用代码库时需要记住的代码量和变化。
图7
多态性提供了另一种思考OOP中抽象概念的方法,其中对象之间的相似性可以类似地实现。虽然我们永远不想驾驶三轮车到任何需要汽车行驶的地方,但它们都有轮子,并且都可以通过相同的滚动功能来使用。在roll函数中,将两个对象抽象为称之为车辆的对象。甚至可以创建一个它们都从中继承的车辆父类。可以看到这些不同的构建块如何开始合并,并以新的有趣的方式一起工作。
Python中的面向对象编程——一切都是一个对象
汽车、自行车、车轮、问候语……在面向对象编程中,一切都可以是对象。假设我们可以:
1.平衡抽象对象的工作方式
2.封装内部细节
3.从相似对象继承行为
4.将较小的对象组合成较大的对象,以及
5.对实现进行变形,以跨各种对象使用类似的功能。
此时,你也可以成为面向对象的程序员。
注:本文学习整理自pythoninoffice.com,供有兴趣的朋友参考。