什么是面向对象编程?
引用百度百科解释:
面向对象程序设计(Object Oriented Programming)作为一种新方法,其本质是以建立模型体现出来的抽象思维过程和面向对象的方法。模型是用来反映现实世界中事物特征的。任何一个模型都不可能反映客观事物的一切具体特征,只能对事物特征和变化规律的一种抽象,且在它所涉及的范围内更普遍、更集中、更深刻地描述客体的特征。通过建立模型而达到的抽象是人们对客体认识的深化。
既然说到面向对象,也就不能不提面向过程。
那么是什么是面向过程呢?
“面向过程”(Procedure Oriented)是一种以过程为中心的编程思想。“面向过程”也可称之为“面向记录”编程思想,他们不支持丰富的“面向对象”特性(比如继承、多态),并且它们不允许混合持久化状态和域逻辑。就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
或许还会有人问,面向过程和面向对象的区别是什么?
这个聪哥哥我也不知道,所以参考一位博友朋友所说的:
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;
面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
可以拿生活中的实例来理解面向过程与面向对象,例如五子棋,面向过程的设计思路就是首先分析问题的步骤:
1、开始游戏,2、黑子先走,3、绘制画面,4、判断输赢,5、轮到白子,6、绘制画面,7、判断输赢,8、返回步骤2,9、输出最后结果。把上面每个步骤用不同的方法来实现。
如果是面向对象的设计思想来解决问题。面向对象的设计则是从另外的思路来解决问题。整个五子棋可以分为:
1、黑白双方,这两方的行为是一模一样的,2、棋盘系统,负责绘制画面,3、规则系统,负责判定诸如犯规、输赢等。第一类对象(玩家对象)负责接受用户输入,并告知第二类对象(棋盘对象)棋子布局的变化,棋盘对象接收到了棋子的变化就要负责在屏幕上面显示出这种变化,同时利用第三类对象(规则系统)来对棋局进行判定。
可以明显地看出,面向对象是以功能来划分问题,而不是步骤。同样是绘制棋局,这样的行为在面向过程的设计中分散在了多个步骤中,很可能出现不同的绘制版本,因为通常设计人员会考虑到实际情况进行各种各样的简化。而面向对象的设计中,绘图只可能在棋盘对象中出现,从而保证了绘图的统一。
面向对象和面向过程编程的优缺点是什么?
面向过程
优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源,比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。
缺点:没有面向对象易维护、易复用、易扩展
面向对象
优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护
缺点:性能比面向过程低
今天聪哥哥我主要讲的是类和实例、访问限制、继承和多态、获取对象信息、实例属性和类属性等五个方面。
有一定编程语言基础的朋友们,可以联系到自身经常用到的编程语言,通过对比进行学习,同时也可以温习。
一、类和实例
面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。
示例一:
# -*- coding: utf-8 -*-
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
def get_grade(self):
if self.score >= 90:
return 'A'
elif self.score >= 60:
return 'B'
else:
return 'C'
lisa = Student("Lisa",100)
bart = Student("Bart",50)
print(lisa.name,lisa.get_grade())
print(bart.name,bart.get_grade())
聪哥哥有话说:
(1)类是创建实例的模板,而实例则是一个一个具体的对象,各个实例拥有的数据都互相独立,互不影响;
(2)方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据;
(3)通过在实例上调用方法,我们就直接操作了对象内部的数据,但无需知道方法内部的实现细节。
二、访问限制
在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑。
示例一(如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__
,在Python中,实例的变量名如果以__
开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问,所以,我们把Student类改一改):
# -*- coding: utf-8 -*-
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))
bart = Student("聪哥哥",100)
print(bart.__name)
改完后,对于外部代码来说,没什么变动,但是已经无法从外部访问实例变量.__name
和实例变量.__score
了
结果如图:
三、继承和多态
在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)。
继承的好处是不言而喻的,继承是为了复用,复用是为了降低代码冗余。
来一段示例说明,比如动物类继承示例
示例一:
# -*- coding: utf-8 -*-
class Animal(object):
def run(self):
print('Animal is running...')
class Dog(Animal):
def run(self):
print('Dog is running...')
def eat(self):
print('Eating meat...')
class Cat(Animal):
pass
dog = Dog()
dog.run()
dog.eat()
cat = Cat()
cat.run()
聪哥哥有话说:
继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写。
四、获取对象信息
当我们拿到一个对象的引用时,如何知道这个对象是什么类型、有哪些方法呢?
基本类型都可以用type()来判断,例如:
# -*- coding: utf-8 -*-
print(type(1234))
如图:
继承关系可以使用isinstance()
例如:
# -*- coding: utf-8 -*-
class Animal(object):
def run(self):
print('Animal is running...')
class Dog(Animal):
def run(self):
print('Dog is running...')
def eat(self):
print('Eating meat...')
class Cat(Animal):
pass
dog = Dog()
cat = Cat()
print(isinstance(cat,Cat))
结果如:
如果要获得一个对象的所有属性和方法,可以使用dir()
函数,它返回一个包含字符串的list,比如,获得一个str对象的所有属性和方法:
# -*- coding: utf-8 -*-
print(dir("ABC"))
结果如图:
聪哥哥有话说:
通过内置的一系列函数,我们可以对任意一个Python对象进行剖析,拿到其内部的数据。要注意的是,只有在不知道对象信息的时候,我们才会去获取对象信息。
五、实例属性和类属性
由于Python是动态语言,根据类创建的实例可以任意绑定属性。
或许有哪位小哥哥或是小姐姐会问什么是动态语言,然后接着又会问,有动态语言,就有与之相反的静态语言,那么什么是静态语言。
最后产生的问题就是什么是动态语言?什么是静态语言?动态语言和静态语言的区别?动态语言和静态语言的优劣?
问题一个一个来回答。
问:什么是动态语言?
答:引用百度百科:动态语言,是指程序在运行时可以改变其结构:新的函数可以被引进,已有的函数可以被删除等在结构上的变化,类型的检查是在运行时做的,优点为方便阅读,清晰明了,缺点为不方便调试。
问:什么是静态语言?
答:静态语言是在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型。
或许有人说,我听不懂这么官方的说辞。
那好,接下来由聪哥哥来通俗解答:动态语言不需要编译即可运行,而静态语言需要编译后才能运行(关于动态语言和静态语言的区别,这个也是答案)。
问:动态语言和静态语言的优劣比较?
答:
静态语言的优势:
(1)由于类型的强制声明,使得IDE有很强的代码感知能力,故,在实现复杂的业务逻辑、开发大型商业系统、以及那些生命周期很长的应用中,依托IDE对系统的开发很有保障;
(2)由于静态语言相对比较封闭,使得第三方开发包对代码的侵害性可以降到最低;
(3)代码运行速度快。
静态语言的劣势:
代码不够简洁。
动态语言的优势:
(1)思维不受束缚,可以任意发挥,把更多的精力放在产品本身上;
(2)集中思考业务逻辑实现,思考过程即实现过程。
动态语言的劣势:
不方便调试,命名容易混淆。
代码示例:
# -*- coding: utf-8 -*-
class Student(object):
name = '聪哥哥'
s = Student() #实例
print(s.name)
聪哥哥有话说:
(1)实例属性属于各个实例所有,互不干扰;
(2)类属性属于类所有,所有实例共享一个属性;
(3)不要对实例属性和类属性使用相同的名字,否则将产生难以发现的错误。
小结:
聪哥哥有话说,对于本章学习,有一定的编程经验人士学习起来,特别是接触过面向对象这个概念,或者是有Java的开发经验,很容易学习。