面向对象开发基础知识
04 Sep 2012面向对象编程(Object-Oriented Programming,OOP)是一个软件开发范式,它基于称为 “对象” 的数据结构的定义,由数据属性和函数组成。这些属性(成员变量)和函数(或方法)定义软件与那个对象可能进行的交互。OOP 的主要好处是,简化您的代码结构,有助于代码重用和维护。
“面向对象” 基础知识
面向对象编程的基本前提是:在您的软件中创建一些对象,这些对象定义一系列应用于该对象的属性和一系列能够检索或修改该对象的属性的方法或函数。car
可能是一个简单的对象示例。与一个 car
关联的数据属性可能包括它的 manufacturer
、model number
、registration number
、color
、cubic capacity
,等等。一个 car
对象提供的方法可能包括 accelerate
、brake
、change gear
、turn
、stop
等等。在 OOP 中,理念是您定义对所有汽车都通用的基本属性和方法,每辆汽车都将采用那个定义的形式,尽管每辆汽车都采用不同的值。本文稍后将介绍,软件开发中有不同的面向对象途径。
常用 OOP 术语
为最大限度地利用本文,您至少应该熟悉面向对象编程及其概念。下面简要描述讨论面向对象开发时使用的一些常用术语。需要说明的是,并非所有 OOP 类型都包含每个概念;例如,基于原型的对象语言(比如 JavaScript)中就没有 “类”。
类
在基于类的面向对象开发中,一个类定义组成一个对象的不同属性和函数。类定义用于生成对象的模板,因此它们应该定义这些对象能够遵守的公共属性和动作。类通常由成员变量和方法构成。
成员变量
对象的成员变量就是该对象的属性。在前面提到的汽车示例中,这些属性包括该汽车的 manufacturer
model
、color
、cubic capacity
,等等。
方法
方法是对象能够执行的动作。例如,一辆汽车能够 accelerate
、brake
、turn
,等等。通常,方法将修改成员变量的值。例如,当一个 car
对象使用 accelerate
方法加速时,它的当前速度属性将增加。许多对象都有一个称为 constructor 的方法,该方法在对象创建后立即被调用。
实例或对象
实例或对象即实际对象本身,而不是用于定义对象的模板。例如,您可能有一个名为 myCar
的对象,它拥有一个汽车模板的属性和方法。在一个对象的实例中,属性将实际拥有值。例如,myCar
可能拥有一个值为 silver
的 color 属性,一个值为 2500
的 cubic capacity 属性。一个对象的属性的当前值称为该对象的状态,该状态可以在该对象的整个生命周期内变化。
继承性
在基于类的 OOP 中,继承性是这样一个过程:子类继承其父类的成员变量和方法。除了继承这些属性和动作之外,子类可以定义自己的成员变量和方法,并提供父类的属性的默认值。例如,您可能有一个 FourByFour
类,它是 Car
类的一个子类。这个子类可以将其父类的 drivetrain 属性的默认值设置为 4WD
(四轮驱动)。另外,它可以定义另一个名为 transfer case 的属性,该属性仅适用 4x4 汽车;并定义一个方法,该方法允许您更改其他普通车辆上没有的低速档(low range gear)。
封装
在基于类的 OOP 中,成员变量通常被定义为私有变量,以免被从类本身的范围外访问或修改。有一些称为 “修改器” 的特殊方法,它们允许您定义可以检索或修改类中的私有成员函数的值的方法。这些方法(通常称为 getters 和 setters)允许程序员使用隐藏的信息,使应用程序和其他类只能访问某些属性。这种技术通常称为 “封装”。
抽象
抽象是通过只定义那些在您对象的当前上下文中对该对象很重要的属性和方法来减小对象的复杂性的过程。例如,当您定义一个 Car
类时,可以通过定义一辆汽车拥有的、对其他类型的车辆(比如有蓬货车、卡车、摩托车等)也常见的所有属性,来将这个类进一步抽象为一个 Vehicle
类。这样,Car
类将从 Vehicle
类继承这些属性,就像一个 Motorcycle
类或 Van
类那样。
多态性
在 OOP 上下文中,多态性意味着可以从它的超类继承方法,而不必提供所有方法的相同实现。例如,您有两个 Car
类的两个子类,一个用于自动挡汽车(我们称其为 ATCar
),另一个用于手动挡汽车(我们称其为 MTCar
)。所有 Car
对象都能加速,因此 ATCar
和MTCar
都将从它们的父类继承 accelerate
方法。但是,在一个 ATCar
中,当引擎达到某个 RPM 级别时,您的 accelerate 方法将自动调用 change gear 方法。结果,您在 ATCar
子类中覆盖了 accelerate
方法的父类定义,而在 MTCar
中,该方法就是子类从 Car
类继承而来的方法。
面向对象的 JavaScript
上一小节介绍的许多概念都是称为基于类的面向对象编程的特定 OOP 范式所专用的。但是,并非所有编程语言都遵守这个范式。另一种常见 OOP 类型是基于原型的面向对象编程,JavaScript 语言中就使用该范式。在本小节中,您将了解 JavaScript 的面向对象实现,一个用例,以及您可能会遇到的一些障碍,特别是当您来自一个基于类的 OOP 环境时。
JavaScript 并不只是一种基本脚本语言
当 JavaScript 首次流行时,它主要用作一种在基本 web 页面上执行一些简单技巧的方法。大多数 JavaScript 用户都不是软件开发人员,他们是图形或 web 设计师,他们可能拥有丰富的 HTML 经验,但他们的编程语言知识很少,甚至没有。HTML 本身在支持生成动态效果方面的功能是非常有限的,而这正是 JavaScript 优势所在。然而,大多数设计师并不实际学习如何用 JavaScript 编程,而只是尽量找到它们需要的代码段,仅仅学习调试该代码段以满足自身需要的所需的知识,然后使用那段小代码。当设计师这样做过几次之后,他们就会误以为他们自己的 JavaScript 水平不错了。
在 web 早期,JavaScript 的功能很有限。但是,它现在已经成长为一个成熟的、功能齐全的编程语言,它不再只用于为网站编写一些简单技巧,而是用于驱动整个富互联网应用程序。事实上,作为一种语言,JavaScript 今天还在以各种方式应用。例如,CouchDB 面向文档数据库管理系统就使用 JavaScript 函数来查询数据库中的数据。
许多 Java 开发人员(以及使用其他更传统的编程语言的开发人员)可能会轻视 JavaScript,认为它是一种基本脚本语言。尽管 JavaScript 已经发展得非常强大,认为它只是用于在网站上执行一些小技巧的误解仍然存在。这是因为大多数使用 JavaScript 的 web 开发人员将使用 jQuery、Prototype 或 Dojo 这样的库来避免为它们编写 JavaScript 的工作。事实上,很多 web 开发人员可能被视为编写 jQuery 应用程序的专家,但对于 JavaScript 本身,他们实际上几乎没有什么专长。很多这样的开发人员没有意识到的是,JavaScript 实际上非常强大,且包含开箱即用的面向对象特性。在本小节中,您将了解这些特性。
基于原型的 OOP
JavaScript 实现的面向对象编程类型不同于 Java™ 代码中使用的类型。尽管 Java 编程基于一个基于类的 OOP 模型,但 JavaScript 基于一个不怎么基于类的 OOP 模型,这个模型称为基于原型的对象方向。对象只在需要的时候才被声明,而不是定义一组用于创建对象的类模板。当一个对象需要从另一个对象继承特性时,它可以简单地克隆一个原型对象的特性。原型 OOP 的一个关键优势是,对象原型可以在运行时修改,这意味着对象结构的定义不是严格的。大多数基于类的 OOP 编程语言不允许类在运行时动态改变(但有几个例外,比如 Perl、Python 和 Ruby)。
原文转自:IBM developerWorks