今日焦点 焦点资讯 营销之道 企业报道 淘宝运营 网站建设 软件开发 400电话
  当前位置: 首页 » 资讯 » 网站建设 » 正文

拥抱原型面向对象编程

放大字体  缩小字体 发布日期:2018-02-18  来源:新格网  作者:新格网  浏览次数:40  【去百度看看】
核心提示:随着 Web 日益成为日常生活的一部分,JavaScript 也开始变得备受关注。JavaScript 是一个经常遭到误解的语言,被认为是一种玩具语言或者一种 “不成熟的 Java? 语言”。JavaScript 最饱受非议的特性之一是它的原型对象系统。尽管不可否认 JavaScript 是存在一些缺陷,但原型对象系统并不在其内。在本文中,我们将了解功能强大、简洁、典雅的 JavaScript 原型的面向对象编程。

Javascript 是最低级的Web 编程接口,随处可见。随着Web 日益成为日常生活的一部分,Javascript 也开始变得备受关注。Javascript 是一个经常遭到误解的语言,被认为是一种玩具语言或者一种“不成熟的Java™ 语言”。Javascript 最饱受非议的特性之一是它的原型对象系统。尽管不可否认Javascript 是存在一些缺陷,但原型对象系统并不在其内。在本文中,我们将了解功能强大、简洁、典雅的Javascript 原型的面向对象编程。

对象的世界

当您开始新的一天时(开车去上班,坐在办公桌前执行一个任务,吃一顿饭,逛逛公园),您通常可以掌控您的世界,或者与之交互,不必了解支配它的具体物理法则。您可以将每天面对的各种系统看作是一个单元,或者是一个对象。不必考虑它们的复杂性,只需关注您与它们之间的交互。

历史

Simula 是一种建模语言,通常被认为是第一个面向对象(Object-oriented, OO) 的语言,随后出现的此类语言包括Smalltalk、C++、Java 和C#。那时,大多数面向对象的语言是通过类来定义的。后来,Self 编程语言(一个类似Smalltalk 的系统)开发人员创建了一种可替代的轻量级方法来定义这类对象,并将这种方法称为基于原型的面向对象编程或者原型对象编程。

终于,使用一种基于原型的对象系统将Javascript 开发了出来,Javascript 的流行将基于原型的对象带入了主流。尽管许多开发人员对此很反感,不过仔细研究基于原型的系统,就会发现它的很多优点。

面向对象的编程(Object-oriented, OO) 试图创建工作原理相似的软件系统,面向对象编程是一个功能强大的、广泛流行的、用于软件开发的建模工具。 面向对象编程之所以流行,是因为它反映了我们观察世界的方法:将世界看作是一个对象集合,可与其他对象进行交互,并且可以采用各种方式对其进行操作。面向对象编程的强大之处在于其两个核心原则:

封装允许开发人员隐藏数据结构的内部工作原理,呈现可靠的编程接口,使用这些编程接口来创建模块化的、适应性强的软件。我们可以将信息封装视为信息隐藏。

继承增强封装功能,允许对象继承其他对象的封装行为。我们可以将信息继承视为是信息共享。

这些原则对于大多数开发人员来说是众所周知的,因为每个主流编程语言都支持面向对象编程(在很多情况下是强制执行的)。尽管所有面向对象语言都以这样或那样的形式支持这两个核心原则,但多年来至少形成了2 种定义对象的不同方法。

在本文中,我们将了解原型对象编程和Javascript 对象模式的优势。

javas<em></em>cript logo

什么是Prototypo?类和原型的关系

类提供对象的抽象定义,为整个类或对象集合定义了共享的数据结构和方法。每个对象都被定义为其类的一个实例。类还有根据其定义和(可选)用户参数来构造类对象的责任。

一个典型的示例是Point 类及其子类Point3D,用来分别定义二维点和三维点。清单1 显示了Java 代码中的类。

清单1. Java Point 类

class Point {

private int x;

private int y;

static Point(int x, int y) {

this.x = x;

this.y = y;

}

int getX() {

return this.x;

}

int getY() {

return this.y;

}

void setX(int val) {

this.x = val;

}

void setY(int val) {

this.y = val;

}

}

Point p1 = new Point(0, 0);

p1.getX() // => 0;

p1.getY() // => 0;

// The Point3D class 'extends' Point, inheriting its behavior

class Point3D extends Point {

private int z;

static Point3D(int x, int y, int z) {

this.x = x;

this.y = y;

this.z = z;

}

int getZ() {

return Z;

}

void setZ(int val) {

this.z = val;

}

}

Point3D p2 = Point3D(0, 0, 0);

p2.getX() // => 0

p2.getY() // => 0

p2.getZ() // => 0

和通过类来定义对象相比,原型对象系统支持一个更为直接的对象创建方法。例如,在Javascript 中,一个对象是一个简单的属性列表。每个对象包含另一个父类或原型的一个特别引用,对象从父类或原型中继承行为。您可以使用 Javascript 模拟Point 示例,如清单2 所示。

清单2. Javascript Point 类

var point = {

x : 0,

y : 0

};

point.x // => 0

point.y // => 0

// creates a new object with point as its prototype, inheriting point's behavior

point3D = Object.create(point);

point3D.z = 0;

point3D.x // => 0

point3D.y // => 0

point3D.z // => 0

传统对象系统和原型对象系统有本质的区别。传统对象被抽象地定义为概念组的一部分,从对象的其他类或组中继承一些特性。相反,原型对象被具体地定义为特定对象,从其他特定对象中继承行为。

因此,基于类的面向对象语言具有双重特性,至少需要2 个基础结构:类和对象。由于这种双重性,随着基于类的软件的发展,复杂的类层次结构继承也将逐渐开发出来。通常无法预测出未来类需要使用的方法,因此,类层次结构需要不断重构,让更改变得更轻松。

基于原型的语言会减少上述双重性需求,促进对象的直接创建和操作。如果没有通过类来束缚对象,则会创建更为松散的类系统,这有助于维护模块性并减少重构需求。

直接定义对象的能力将会加强和简化对象的创建和操作。例如,在清单2 中,仅用一行代码即可声明您的point 对象:var point = { x: 0, y: 0 };。仅使用这一行代码,就可以获得一个完整的工作对象,从Javascript Object.prototype(比如toString 方法)继承行为。要扩展对象行为,只需使用point 将另一个对象声明为其原型。相反,即使最简洁的传统面向对象语言,也必须先定义一个类,然后在获得可操作对象之前将其实例化。要继承有关行为,可能需要定义另一个类来扩展第一个类。

原型模式理论上比较简单。作为人类,我们往往习惯于从原型方面思考问题。例如,Steve Yegge 在博客文章“The Universal Design Pattern”(请参阅参考资料)中讨论过,以橄榄球运动员Emmitt Smith 为例,谁拥有速度、敏捷性和剪力,谁就将成为美国国家橄榄球联盟(National Football League,NFL)所有新成员的榜样。当一个新跑步运动员LT 发挥超常捡到球时,评论员通常会这样说:

“LT 有双Emmitt 的腿。”

“他就像Emmitt 一样自由穿过终点线。”

“他跑一英里只用5 分钟!”

评论员以原型对象Emmitt Smith 为模型来评论新对象LT。在Javascript 中,这类模型看起来如清单3 所示。

清单3. Javascript 模型

var emmitt = {

// ... properties go here

};

var lt = Object.create(emmitt);

// ... add other properties directly to lt

您可以将该示例与经典模型进行比较,在经典模型中您可能会定义一个继承自FootballPlayer 类的RunningBack 类。LT 和Emmitt 可能是RunningBack 的实例。这些Java 代码编写的类看起来如清单4 所示。

清单4. 3 个Java 类

class FootballPlayer {

private string name;

private string team;

static void FootballPlayer() { }

string getName() {

return this.name;

}

string getTeam() {

return this.team;

}

void setName(string val) {

this.name = val;

}

void setTeam(string val) {

this.team = val;

}

}

class RunningBack extends FootballPlayer {

private bool offensiveTeam = true;

bool isOffesiveTeam() {

return this.offensiveTeam;

}

}

RunningBack emmitt = new RunningBack();

RunningBack lt   = new RunningBack();

经典模型通常伴随着极大的概念上的负担,但是对类实例emmitt 和lt(您得到的原型模型),并没有提供细小的控制。(公平地说,FootballPlayer 类并不是100% 需要,这里提供它只是为了与下一个示例进行比较 )。有时,这项开销是有益的,但通常都是一个包袱。

 
 
[ 资讯搜索 ]  [ 加入收藏 ]  [ 告诉好友 ]  [ 打印本文 ]  [ 违规举报 ]  [ 关闭窗口 ]

 
0条 [查看全部]  相关评论

 
网站首页 | 关于我们 | 联系方式 | 使用协议 | 版权隐私 | 网站地图 | 排名推广 | 广告服务 | 积分换礼 | 网站留言 | RSS订阅 | 皖ICP备2021004516号-14
企业800网 · 提供技术支持