oop是面向对象编程(设计) 面向对象程序设计(英语:Object Oriented Programming,缩写:OOP),指一种程序设计范型,同时也是一种程序开发的方法论。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性。基本理论
一项由 Deborah J. Armstrong 进行的长达40年之久的计算机著作调查显示出了一系列面向对象程序设计的基本理论。它们是:
类
类(Class)定义了一件事物的抽象特点。通常来说,类定义了事物的属性和它可以做到的(它的行为)。举例来说,"狗"这个类会包含狗的一切基础特征,例如它的孕育、毛皮颜色和吠叫的能力。类可以为程序提供模版和结构。一个类的方法和属性被称为"成员"。 我们来看一段伪代码:
类狗 开始 私有成员: 孕育 毛皮颜色 公有成员: 吠叫() 结束
在这串代码中,我们声明了一个类,这个类具有一些狗的基本特征。关于公有成员和私有成员,请参见下面的继承性一节。
对象
对象(Object)是类的实例。例如,"狗"这个类列举狗的特点,从而使这个类定义了世界上所有的狗。而莱丝这个对象则是一条具体的狗,它的属性也是具体的。狗有皮毛颜色,而莱丝的皮毛颜色是棕白色的。因此,莱丝就是狗这个类的一个实例。一个具体对象属性的值被称作它的"状态"。
假设我们已经在上面定义了狗这个类,我们就可以用这个类来定义对象:
定义莱丝是狗 莱丝.毛皮颜色:=棕白色 莱丝.吠叫()
我们无法让狗这个类去吠叫,但是我们可以让对象"莱丝"去吠叫,正如狗可以吠叫,但没有具体的狗就无法吠叫。
方法
方法(Method)是一个类能做的事情,但方法并没有去做这件事。作为一条狗,莱丝是会吠叫的,因此"吠叫()"就是它的一个方法。与此同时,它可能还会有其它方法,例如"坐下()",或者"吃()"。 对一个具体对象的方法进行调用并不影响其它对象,正如所有的狗都会叫,但是你让一条狗叫不代表所有的狗都叫。 如下例:
定义莱丝是狗 定义泰尔是狗 莱丝.吠叫()
则泰尔是不会吠叫的,因为这里的吠叫只是对对象"莱丝"进行的。
消息传递机制
一个对象通过接受消息、处理消息、传出消息或使用其他类的方法来实现一定功能,这叫做消息传递机制(Message Passing)。
继承性
继承性(Inheritance)是指,在某种情况下,一个类会有"子类"。子类比原本的类(称为父类)要更加具体化,例如,"狗"这个类可能会有它的子类"牧羊犬"和"奇瓦瓦犬"。在这种情况下,"莱丝"可能就是牧羊犬的一个实例。子类会继承父类的属性和行为,并且也可包含它们自己的。我们假设"狗"这个类有一个方法叫做"吠叫()"和一个属性叫做"毛皮颜色"。它的子类(前例中的牧羊犬和奇瓦瓦犬)会继承这些成员。这意味着程序员只需要将相同的代码写一次。 在伪代码中我们可以这样写:
类牧羊犬:继承狗 定义莱丝是牧羊犬 莱丝.吠叫() /* 注意这里调用的是狗这个类的吠叫属性。 */
回到前面的例子,"牧羊犬"这个类可以继承"毛皮颜色"这个属性,并指定其为棕白色。而"奇瓦瓦犬"则可以继承"吠叫()"这个方法,并指定它的音调高于平常。子类也可以加入新的成员,例如,"奇瓦瓦犬"这个类可以加入一个方法叫做"颤抖()"。设若用"牧羊犬"这个类定义了一个实例"莱丝",那么莱丝就不会颤抖,因为这个方法是属于奇瓦瓦犬的,而非牧羊犬。事实上,我们可以把继承理解为"是"。例如,莱丝"是"牧羊犬,牧羊犬"是"狗。因此,莱丝既继承了牧羊犬的属性,又继承了狗的属性。 我们来看伪代码:
类奇瓦瓦犬:继承狗 开始 公有成员: 颤抖() 结束 类牧羊犬:继承狗 定义莱丝是牧羊犬 莱丝.颤抖() /* 错误:颤抖是奇瓦瓦犬的成员方法。 */
当一个类从多个父类继承时,我们称之为"多重继承"。多重继承并不总是被支持的,因为它很难理解,又很难被好好使用。
封装性
具备封装性(Encapsulation)的面向对象程序设计隐藏了某一方法的具体执行步骤,取而代之的是通过消息传递机制传送消息给它。因此,举例来说,"狗"这个类有"吠叫()"的方法,这一方法定义了狗具体该通过什么方法吠叫。但是,莱丝的朋友蒂米并不需要知道它到底如何吠叫。 从实例来看:
/* 一个面向过程的程序会这样写: */
定义莱丝 莱丝.设置音调(5) 莱丝.吸气() 莱丝.吐气() /* 而当狗的吠叫被封装到类中,任何人都可以简单地使用: */ 定义莱丝是狗 莱丝.吠叫()
封装是通过限制只有特定类的实例可以访问这一特定类的成员,而它们通常利用接口实现消息的传入传出。举个例子,接口能确保幼犬这一特征只能被赋予狗这一类。通常来说,成员会依它们的访问权限被分为3种:公有成员、私有成员以及保护成员。有些语言更进一步:Java可以限制同一包内不同类的访问;C#和VB.NET保留了为类的成员聚集准备的关键字:internal(C#)和Friend(VB.NET);Eiffel语言则可以让用户指定哪个类可以访问所有成员。
多态性
多态性(Polymorphism)指方法在不同的类中调用可以实现的不同结果。因此,2个甚至更多的类可以对同一消息作出不同的反应。举例来说,狗和鸡都有"叫()"这一方法,但是调用狗的"叫()",狗会吠叫;调用鸡的"叫()",鸡则会啼叫。 我们将它体现在伪代码上:
类狗 开始 公有成员: 叫() 开始 吠叫() 结束 结束 类鸡 开始 公有成员: 叫() 开始 啼叫() 结束 结束 定义莱丝是狗 定义鲁斯特是鸡 莱丝.叫() 鲁斯特.叫()
这样,同样是叫,莱丝和鲁斯特做出的反应将大不相同。多态性的概念可以用在运算符重载上,本文不再赘述。
抽象性
抽象(Abstraction)是简化复杂的现实问题的途径,它可以为具体问题找到最恰当的类定义,并且可以在最恰当的继承级别解释问题。举例说明,莱丝在大多数时候都被当作一条狗,但是如果想要让它做牧羊犬做的事,你完全可以调用牧羊犬的方法。如果狗这个类还有动物的父类,那么你完全可以视莱丝为一个动物。
OOP名词释意
编程范型 对于OOP的准确定义及其本意存在着不少争论。
通常,OOP被理解为一种将程序分解为封装数据及相关操作的模块而进行的编程方式。有别于其它编程方式,OOP中的与某数据类型相关的一系列操作都被有机地封装到该数据类型当中,而非散放于其外,因而OOP中的数据类型不仅有着状态,还有着相关的行为。OOP理论,及与之同名的OOP实践相结合创造出了新的一个编程架构;OOP思想被广泛认为是非常有用的,以致一套新的编程范型被创造了出来。(其它的编程范型例如函数式编程或过程序编程专注于程序运行的过程,而逻辑编程专注于引发程序代码执行的断言)
对面向模拟系统的语言(如:SIMULA 67)的研究及对高可靠性系统架构(如:高性能操作系统和CPU的架构)的研究最终导致了OOP的诞生。