10

我来自面向对象语言的课程,最近我一直在学习那些花哨的动态语言(JavaScript、Python 和 Lua),我想要一些关于如何在这些语言中使用 OO 的技巧。了解这种方法的缺陷和缺点以及与传统 OO 相比的优势将很有用。

我得到的一般概念是,基于原型的 OO 基本上是使用对象进行编程,但没有关于如何使用它们的标准,而在普通 OO 中,有一种固定的预定义方式来制作和使用对象。

总而言之,这种方法的优点、缺点和丑陋的部分是什么?

4

5 回答 5

13

基于原型的 OO 不适合静态类型检查,有些人可能认为这是一件坏事或丑陋的事情。基于原型的 OO确实具有创建新对象的标准方法,即克隆和修改现有对象。还可以建工厂等等。

我认为人们最喜欢(“好”)的是基于原型的 OO 非常轻巧且灵活,提供了非常高的功率重量比

有关如何使用基于原型的 OO 的提示,一个很好的起点是关于The Power of Simplicity的原始 Self 论文。

于 2008-12-22T04:34:49.813 回答
7

为了节省带宽,这里是我关于“如何在 JavaScript 中模拟“类”?(有或没有第三方库)”的答案的链接。它包含更多参考资料和示例。

简短的回答:JavaScript 原型OO的核心是委托。在这种 OOP 风格中,同一个“类”的不同对象可以将方法和属性的处理委托给同一个原型(通常是第三个对象):

var foo = {
    property: 42,
    inc: function(){
        ++this.counter;
    },
    dec: function(){
        --this.counter;
    }
};
// Note: foo does not define `counter`.

让我们为以 foo 作为原型的对象创建一个构造函数。实际上,所有未处理的都将委托给 foo。

var Bar = function(){
    this.counter = 0;
};
Bar.prototype = foo;  // This is how we set up the delegation.

// Some people refer to Bar (a constructor function) as "class".

var bar = new Bar();

console.log(bar.counter);  // 0 --- Comes from bar itself
console.log(bar.property); // 42 --- Not defined in bar, comes from foo

bar.inc();  // Not defined in bar => delegated to foo
bar.inc();
bar.dec();  // Not defined in bar => delegated to foo
// Note: foo.inc() and foo.dec() are called but this === bar
// that is why bar is modified, not foo.

console.log(bar.counter);  // 1 --- Comes from bar itself

让我们inc()直接在 bar 上定义:

bar.inc = function(){
    this.counter = 42;
};

bar.inc();  // Defined in bar => calling it directly.
            // foo.inc() is not even called.
console.log(bar.counter);  // 42 --- Comes from bar

设置单一继承链:

var Baz = function(){
    this.counter = 99;
};
Baz.protype = new Bar();

var baz = new Baz();

console.log(baz.counter); // 99
baz.inc();
console.log(baz.counter); // 100

console.log(baz instanceof Baz);    // true
console.log(baz instanceof Bar);    // true
console.log(baz instanceof Object); // true

整齐,嗯?

于 2008-12-22T03:15:34.387 回答
2

在担心如何在 JavaScript 中模拟基于类的继承之前,请快速阅读JavaScript 中的原型继承

于 2009-01-03T00:50:41.713 回答
1

经典继承在灵活性方面存在固有缺陷,因为我们说“这个对象属于这种类型,没有其他类型”。一些语言引入了多重继承来缓解这种情况,但多重继承有其自身的缺陷,因此纯组合优于继承(在静态类型语言中,继承是运行时而不是编译时机制)的好处变得很明显。

将组合的概念提升到这个“纯”级别,我们可以完全消除经典继承以及静态类型。通过在运行时组合对象并将它们用作蓝图(原型方法),我们无需担心通过继承过于紧密地装箱对象,也无需为多重继承方法中固有的问题而负担。

所以原型意味着更灵活的模块开发。

当然,说不用静态类型就很容易开发是另一回事。海事组织,它不是。

于 2010-10-18T10:31:26.690 回答
0

好的,首先,原型模型在现实中并没有什么不同。Smalltalk 使用类似的方案。该类是具有类方法的对象。

从类POV来看,一个类实际上是具有相同数据、所有相同方法的对象的等价类;您可以将向原型添加方法视为创建新子类。

实现很简单,但是很难进行有效的类型检查。

于 2008-12-22T02:31:15.880 回答