基于原型的面向对象。黄金三镖客?

时间:2008-12-22 02:25:02

标签: javascript python language-agnostic lua oop

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

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

总之,这种方法的好处,坏处和丑处是什么?

5 个答案:

答案 0 :(得分:13)

基于Prototype的OO很难用于静态类型检查,有些人可能认为这是一个坏的或丑陋的事情。基于原型的OO 具有创建新对象的标准方法,您克隆和修改现有对象。你也可以建立工厂等。

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

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

答案 1 :(得分:7)

为了节省带宽,这里是指向my answer on "How can I emulate “classes” in JavaScript? (with or without a third-party library)"的链接。它包含更多参考资料和示例。

简短的回答: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.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

整洁,嗯?

答案 2 :(得分:2)

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

答案 3 :(得分:1)

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

将构图的概念带到这个“纯粹”的层面,我们可以完全消除经典继承和静态类型。通过在运行时编写对象并将它们用作蓝图(原型方法),我们不需要通过继承过于关注拳击对象,也不会担心多重继承方法中固有的问题。

因此,原型意味着更灵活的模块开发。

当然,在没有静态打字的情况下开发是很容易的,这是另一回事。 IMO,它不是。

答案 4 :(得分:0)

好的,首先,原型模型在现实中并非完全不同; Smalltalk使用类似的方案;该类是一个带有类方法的对象。

从类POV看,一个类实际上是具有相同数据的对象的等价类,以及所有相同的方法;你可以看一下在原型中添加一个方法来创建一个新的子类。

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