文章目录
- 定义一:面对对象是一种编程思想
- 定义一:面向对象是一种抽象
- 1、面向对象的两个基本概念
- 2、面向对象的三大特性
- 定义一:你是土豪,全家都是土豪
- 面向对象编程基础
- 类和对象
- 定义类
- 创建和使用对象
- 访问可见性问题
- 面向对象的支柱
定义一:面对对象是一种编程思想
类和对象都是面向对象中的重要概念。面向对象是一种编程思想,即按照真实世界的思维方式构建软件系统。
例如,在真实世界的校园里有学生和老师,学生有学号、姓名、所在班级等属性(数据),还有学习、提问、吃饭和走路等动作(方法)。如果我们要开发一个校园管理系统,那么在构建软件系统时,也会有学生和老师等“类”,张同学、李同学是学生类的个体,被称为“对象”,“对象”也被称为“实例”。
定义一:面向对象是一种抽象
1、面向对象的两个基本概念
编程语言中,一般有两种编程思维,面向过程和面向对象。
面向过程,看重的是解决问题的过程。
这好比我们解决日常生活问题差不多,分析解决问题的步骤,然后一步一步的解决。
而面向对象是一种抽象,抽象是指用分类的眼光去看世界的一种方法。
Python 就是一门面向对象的语言,
如果你学过 Java ,就知道 Java 的编程思想就是:万事万物皆对象。Python 也不例外,在解决实际问题的过程中,可以把构成问题事务分解成各个对象。
面向对象都有两个基本的概念,分别是类和对象。
- 类
用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 对象
通过类定义的数据结构实例。
2、面向对象的三大特性
面向对象的编程语言,也有三大特性,继承,多态和封装性。
- 继承
即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。
例如:一个 Dog 类型的对象派生自 Animal 类,这是模拟"是一个(is-a)"关系(例图,Dog 是一个 Animal )。
- 多态
它是指对不同类型的变量进行相同的操作,它会根据对象(或类)类型的不同而表现出不同的行为。
- 封装性
“封装”就是将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体(即类);封装的目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口,一特定的访问权限来使用类的成员。
定义一:你是土豪,全家都是土豪
面向对象编程基础
活在当下的程序员应该都听过"面向对象编程"一词,也经常有人问能不能用一句话解释下什么是"面向对象编程",我们先来看看比较正式的说法。
"把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归纳为类(class),通过类的封装(encapsulation)隐藏内部细节,通过继承(inheritance)实现类的特化(specialization)和泛化(generalization),通过多态(polymorphism)实现基于对象类型的动态分派。"
这样一说是不是更不明白了。所以我们还是看看更通俗易懂的说法,下面这段内容来自于知乎。
说明: 以上的内容来自于网络,不代表作者本人的观点和看法,与作者本人立场无关,相关责任不由作者承担。
之前我们说过"程序是指令的集合",我们在程序中书写的语句在执行时会变成一条或多条指令然后由CPU去执行。当然为了简化程序的设计,我们引入了函数的概念,把相对独立且经常重复使用的代码放置到函数中,在需要使用这些功能的时候只要调用函数即可;如果一个函数的功能过于复杂和臃肿,我们又可以进一步将函数继续切分为子函数来降低系统的复杂性。但是说了这么多,不知道大家是否发现,所谓编程就是程序员按照计算机的工作方式控制计算机完成各种任务。但是,计算机的工作方式与正常人类的思维模式是不同的,如果编程就必须得抛弃人类正常的思维方式去迎合计算机,编程的乐趣就少了很多,"每个人都应该学习编程"这样的豪言壮语就只能说说而已。当然,这些还不是最重要的,最重要的是当我们需要开发一个复杂的系统时,代码的复杂性会让开发和维护工作都变得举步维艰,所以在上世纪60年代末期,"软件危机"、"软件工程"等一系列的概念开始在行业中出现。
当然,程序员圈子内的人都知道,现实中并没有解决上面所说的这些问题的"银弹",真正让软件开发者看到希望的是上世纪70年代诞生的Smalltalk编程语言中引入的面向对象的编程思想(面向对象编程的雏形可以追溯到更早期的Simula语言)。按照这种编程理念,程序中的数据和操作数据的函数是一个逻辑上的整体,我们称之为“对象”,而我们解决问题的方式就是创建出需要的对象并向对象发出各种各样的消息,多个对象的协同工作最终可以让我们构造出复杂的系统来解决现实中的问题。
说明: 当然面向对象也不是解决软件开发中所有问题的最后的“银弹”,所以今天的高级程序设计语言几乎都提供了对多种编程范式的支持,Python也不例外。
类和对象
简单的说,类是对象的蓝图和模板,而对象是类的实例。这个解释虽然有点像用概念在解释概念,但是从这句话我们至少可以看出,类是抽象的概念,而对象是具体的东西。在面向对象编程的世界中,一切皆为对象,对象都有属性和行为,每个对象都是独一无二的,而且对象一定属于某个类(型)。当我们把一大堆拥有共同特征的对象的静态特征(属性)和动态特征(行为)都抽取出来后,就可以定义出一个叫做“类”的东西。
定义类
在Python中可以使用class
关键字定义类,然后在类中通过之前学习过的函数来定义方法,这样就可以将对象的动态特征描述出来,代码如下所示。
class Student(object):
# __init__是一个特殊方法用于在创建对象时进行初始化操作
# 通过这个方法我们可以为学生对象绑定name和age两个属性
def __init__(self, name, age):
self.name = name
self.age = age
def study(self, course_name):
print('%s正在学习%s.' % (self.name, course_name))
# PEP 8要求标识符的名字用全小写多个单词用下划线连接
# 但是部分程序员和公司更倾向于使用驼峰命名法(驼峰标识)
def watch_movie(self):
if self.age < 18:
print('%s只能观看《熊出没》.' % self.name)
else:
print('%s正在观看岛国爱情大电影.' % self.name)
说明: 写在类中的函数,我们通常称之为(对象的)方法,这些方法就是对象可以接收的消息。
创建和使用对象
当我们定义好一个类之后,可以通过下面的方式来创建对象并给对象发消息。
def main():
# 创建学生对象并指定姓名和年龄
stu1 = Student('骆昊', 38)
# 给对象发study消息
stu1.study('Python程序设计')
# 给对象发watch_av消息
stu1.watch_movie()
stu2 = Student('王大锤', 15)
stu2.study('思想品德')
stu2.watch_movie()
if __name__ == '__main__':
main()
访问可见性问题
对于上面的代码,有C++、Java、C#等编程经验的程序员可能会问,我们给Student
对象绑定的name
和age
属性到底具有怎样的访问权限(也称为可见性)。因为在很多面向对象编程语言中,我们通常会将对象的属性设置为私有的(private)或受保护的(protected),简单的说就是不允许外界访问,而对象的方法通常都是公开的(public),因为公开的方法就是对象能够接受的消息。在Python中,属性和方法的访问权限只有两种,也就是公开的和私有的,如果希望属性是私有的,在给属性命名时可以用两个下划线作为开头,下面的代码可以验证这一点。
class Test:
def __init__(self, foo):
self.__foo = foo
def __bar(self):
print(self.__foo)
print('__bar')
def main():
test = Test('hello')
# AttributeError: 'Test' object has no attribute '__bar'
test.__bar()
# AttributeError: 'Test' object has no attribute '__foo'
print(test.__foo)
if __name__ == "__main__":
main()
但是,Python并没有从语法上严格保证私有属性或方法的私密性,它只是给私有的属性和方法换了一个名字来妨碍对它们的访问,事实上如果你知道更换名字的规则仍然可以访问到它们,下面的代码就可以验证这一点。之所以这样设定,可以用这样一句名言加以解释,就是"We are all consenting adults here"。因为绝大多数程序员都认为开放比封闭要好,而且程序员要自己为自己的行为负责。
class Test:
def __init__(self, foo):
self.__foo = foo
def __bar(self):
print(self.__foo)
print('__bar')
def main():
test = Test('hello')
test._Test__bar()
print(test._Test__foo)
if __name__ == "__main__":
main()
在实际开发中,我们并不建议将属性设置为私有的,因为这会导致子类无法访问(后面会讲到)。所以大多数Python程序员会遵循一种命名惯例就是让属性名以单下划线开头来表示属性是受保护的,本类之外的代码在访问这样的属性时应该要保持慎重。这种做法并不是语法上的规则,单下划线开头的属性和方法外界仍然是可以访问的,所以更多的时候它是一种暗示或隐喻,关于这一点可以看看我的《Python - 那些年我们踩过的那些坑》文章中的讲解。
面向对象的支柱
面向对象有三大支柱:封装、继承和多态。后面两个概念在下一个章节中进行详细的说明,这里我们先说一下什么是封装。我自己对封装的理解是"隐藏一切可以隐藏的实现细节,只向外界暴露(提供)简单的编程接口"。我们在类中定义的方法其实就是把数据和对数据的操作封装起来了,在我们创建了对象之后,只需要给对象发送一个消息(调用方法)就可以执行方法中的代码,也就是说我们只需要知道方法的名字和传入的参数(方法的外部视图),而不需要知道方法内部的实现细节(方法的内部视图)。