Ruby中的实现也是类似的:也使用了完全动态的类(顺便说一下在当前版本的Python中,与Ruby和ECMAScript的对比,放大类(原型)不行的),我们可以彻底改变对象(或类)的特性(在类上添加方法/属性,而这些变化会影响已经存在的对象),但是,它不能的动态改变一个对象的类。
但是,这篇文章不是专门针对Python和Ruby的,因此我们不多说了,我们来继续讨论ECMAScript本身。
但在此之前,我们还得再看一下在一些OOP里有的“语法糖”,因为很多之前关于JavaScript的文章往往会文这些问题。
本节唯一需要注意的错误句子是:“JavaScript不是类,它有原型,可以代替类”。 非常有必要知道并非所有基于类的实现都是完全不一样的,即便我们可能会说“JavaScript是不同的”,但也有必要考虑(除了“类”的概念)还有其他相关的特性呢。
各种OOP实现的其它特性
本节我们简要介绍一下其它特性和各种OOP实现中关于代码重用的方式,也包括ECMAScript中的OOP实现。 原因是,之前出现的关于JavaScript中关于OOP的实现是有一些习惯性的思维限制,唯一主要的要求是,应该在技术上和思想上加以证明。不能说没发现和其它OOP实现里的语法糖功能,就草率认为JavaScript不是不是纯粹的OOP语言,这是不对滴。
多态
在ECMAScript中对象有几种含义的多态性。
例如,一个函数可以应用于不同的对象,就像原生对象的特性(因为这个值在进入执行上下文时确定的):
复制代码 代码如下:
function test() {
alert([this.a, this.b]);
}
test.call({a: 10, b: 20}); // 10, 20
test.call({a: 100, b: 200}); // 100, 200
var a = 1;
var b = 2;
test(); // 1, 2
不过,也有例外:Date.prototype.getTime()方法,根据标准这个值总是应该有一个日期对象,否则就会抛出异常。
复制代码 代码如下:
alert(Date.prototype.getTime.call(new Date())); // time
alert(Date.prototype.getTime.call(new String(''))); // TypeError
所谓函数定义时的参数多态性也就等价于所有数据类型,只不过接受多态性参数(例如数组的.sort排序方法和它的参数——多态的排序功能)。顺便说一下,上面的例子也可以被视为是一种参数多态性。
原型里方法可以被定义为空,所有创建的对象应重新定义(实现)该方法(即“一个接口(签名),多个实现”)。
多态性和我们上面提到的Duck类型是有关的:即对象的类型和在层次结构中的位置不是那么重要,但如果它有所有必要的特征,它可以很容易地接受(即通用接口很重要,实现则可以多种多样)。
封装
关于封装,往往会有错误的看法。本节我们讨论一下一些OOP实现里的语法糖——也就是众所周知的修饰符:在这种情况下,我们将讨论一些OOP实现便捷的“糖” -众所周知的修饰符:private,protected和public(或者称为对象的访问级别或访问修饰符)。
在这里我要提醒一下封装的主要目的:封装是一个抽象的增加,而不是选拔个直接往你的类里写入一些东西的隐藏“恶意黑客”。
这是一个很大的错误:为了隐藏使用隐藏。
访问级别(private,protected和public),为了方便编程在很多面向对象里都已经实现了(真的是非常方便的语法糖),更抽象地描述和构建系统。
这些可以在一些实现里看出(如已经提到的Python和Ruby)。一方面(在Python中),这些__private _protected属性(通过下划线这个命名规范),从外部不可访问。 另一方面,Python可以通过特殊的规则从外部访问(_ClassName__field_name)。
复制代码 代码如下: