javascript中的经典继承与原型继承 [英] classical inheritance vs prototypal inheritance in javascript

查看:30
本文介绍了javascript中的经典继承与原型继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在谷歌上搜索了很多链接,但无法很好地了解经典继承和原型继承之间的区别?

I have googled so many links and can't get good idea about the difference between classical inheritance and prototypal inheritance?

我从这些中学到了一些东西,但我仍然对这些概念感到困惑.

I have learned some things from these but I'm still confused about the concepts.

http://aaditmshah.github.io/why-prototypal-继承事项/

经典继承

// Shape - superclass
function Shape() {
  this.x = 0;
  this.y = 0;
}

//superclass method
Shape.prototype.move = function(x, y) {
    this.x += x;
    this.y += y;
    console.info("Shape moved.");
};

// Rectangle - subclass
function Rectangle() {
  Shape.call(this); //call super constructor.
}

//subclass extends superclass
Rectangle.prototype = Object.create(Shape.prototype);

经典继承内部是否使用原型继承?

Does classical inheritance use prototypal inheritance inside?

http://aaditmshah.github.io/why-prototypal-inheritance-matters/

从上面的链接中,我了解到我们不能在经典继承中在运行时添加新方法.这个对吗?但是你可以检查上面的代码我可以通过原型在运行时添加移动"方法和任何方法.所以这是基于原型的经典继承?如果是这样,什么是实际的经典继承和原型继承?我对此感到困惑.

From above link, I learned we can't add new methods at run time in classical inheritance. Is this correct? But you can check the above code I can add "move" method and any methods at run time through prototype. So this is prototype based classical inheritance? If so what is actual classical inheritance and prototype inheritance? I am confused about that.

原型继承.

function Circle(radius) {
    this.radius = radius;
}
Circle.prototype.area = function () {
    var radius = this.radius;
    return Math.PI * radius * radius;
};
Circle.prototype.circumference: function () {
    return 2 * Math.PI * this.radius;
};
var circle = new Circle(5);
var circle2 = new Circle(10);

这类似于经典继承吗?我对什么是原型继承完全感到困惑?什么是经典继承?为什么经典继承不好?

Is this similar to classical inheritance? I'm totally confused about what is prototypal inheritance? What is classical inheritance? Why is classical inheritance bad?

你能给我一个简单的例子,让我以简单的方式更好地理解这些.

Can you give me a simple example for better understanding these in a simple manner.

谢谢,

湿婆

推荐答案

您在问题中演示的两个代码示例都使用了原型继承.事实上,你用 JavaScript 编写的任何面向对象的代码都是原型继承的范式.JavaScript 根本就没有经典的继承.这应该会让事情变得更清楚:

Both the code samples you demonstrated in your question make use of prototypal inheritance. In fact any object-oriented code you write in JavaScript is a paradigm of prototypal inheritance. JavaScript simply doesn't have classical inheritance. This should clear things up a bit:

                                   Inheritance
                                        |
                         +-----------------------------+
                         |                             |
                         v                             v
                    Prototypal                     Classical
                         |
         +------------------------------+
         |                              |
         v                              v
Prototypal Pattern             Constructor Pattern

如您所见,原型继承和经典继承是两种不同的继承范式.Self、Lua 和 JavaScript 等一些语言支持原型继承.然而,大多数语言,如 C++、Java 和 C# 都支持经典继承.

As you can see prototypal inheritance and classical inheritance are two different paradigms of inheritance. Some languages like Self, Lua and JavaScript support prototypal inheritance. However most languages like C++, Java and C# support classical inheritance.

原型继承和经典继承都是面向对象的编程范式(即它们处理对象).对象是简单的抽象,它封装了现实世界实体的属性(即它们代表程序中的真实事物).这称为抽象.

Both prototypal inheritance and classical inheritance are object-oriented programming paradigms (i.e. they deal with objects). Objects are simply abstractions which encapsulate the properties of a real world entity (i.e. they represent real word things in the program). This is known as abstraction.

抽象:计算机程序中真实世界事物的表示.

Abstraction: The representation of real world things in computer programs.

理论上,抽象被定义为通过从特定示例中提取共同特征而形成的一般概念".然而,为了便于解释,我们将使用上述定义.

现在有些对象有很多共同点.例如,一辆泥地自行车和一辆哈雷戴维森 (Harley Davidson) 有很多共同点.

Now some objects have a lot of things in common. For example a mud bike and a Harley Davidson have a lot in common.

泥地自行车:

哈雷戴维森:

泥地自行车和哈雷戴维森都是自行车.因此,自行车是泥地自行车和哈雷戴维森的概括.

A mud bike and a Harley Davidson are both bikes. Hence a bike is a generalization of both a mud bike and a Harley Davidson.

                   Bike
                     |
    +---------------------------------+
    |                                 |
    v                                 v
Mud Bike                       Harley Davidson

在上面的例子中,自行车、泥地自行车和哈雷戴维森都是抽象的.然而,自行车是泥地自行车和哈雷戴维森的更笼统的抽象(即泥地自行车和哈雷戴维森都是特定类型的自行车).

In the above example the bike, the mud bike and the Harley Davidson are all abstractions. However the bike is a more general abstraction of the mud bike and the Harley Davidson (i.e. both the mud bike and the Harley Davidson are specific types of bikes).

概括:对更具体抽象的抽象.

在面向对象编程中,我们创建对象(它们是现实世界实体的抽象),我们使用类或原型来创建这些对象的泛化.泛化是通过继承创建的.自行车是泥地自行车的概括.因此,泥地自行车继承了自行车.

In object-oriented programming we create objects (which are abstractions of real world entities) and we use either classes or prototypes to create generalizations of these objects. Generalizations are created via inheritance. A bike is a generalization of a mud bike. Hence mud bikes inherit from bikes.

在经典的面向对象编程中,我们有两种抽象类型:类和对象.如前所述,对象是现实世界实体的抽象.另一方面,类是对象或另一个类的抽象(即它是一种概括).例如,考虑:

In classical object-oriented programming we have two types of abstractions: classes and objects. An object, as mentioned before, is an abstraction of a real world entity. A class on the other hand is an abstraction of an object or another class (i.e. it's a generalization). For example, consider:

+----------------------+----------------+---------------------------------------+
| Level of Abstraction | Name of Entity |                Comments               |
+----------------------+----------------+---------------------------------------+
| 0                    | John Doe       | Real World Entity.                    |
| 1                    | johnDoe        | Variable holding object.              |
| 2                    | Man            | Class of object johnDoe.              |
| 3                    | Human          | Superclass of class Man.              |
+----------------------+----------------+---------------------------------------+

正如您在经典的面向对象编程语言中所见,对象只是抽象(即所有对象的抽象级别为 1),而类只是泛化(即所有类的抽象级别都大于 1).

As you can see in classical object-oriented programming languages objects are only abstractions (i.e. all objects have an abstraction level of 1) and classes are only generalizations (i.e. all classes have an abstraction level greater than 1).

经典的面向对象编程语言中的对象只能通过实例化类来创建:

Objects in classical object-oriented programming languages can only be created by instantiating classes:

class Human {
    // ...
}

class Man extends Human {
    // ...
}

Man johnDoe = new Man();

总而言之,在经典的面向对象编程语言中,对象是现实世界实体的抽象,而类是泛化(即对象或其他类的抽象).

In summation in classical object-oriented programming languages objects are abstractions of real world entities and classes are generalizations (i.e. abstractions of either objects or other classes).

因此,随着抽象级别的提高,实体变得更一般,而随着抽象级别的降低,实体变得更具体.从这个意义上说,抽象级别类似于从更具体的实体到更一般的实体的范围.

Hence as the level of abstraction increases entities become more general and as the level of abstraction decreases entities become more specific. In this sense the level of abstraction is analogous to a scale ranging from more specific entities to more general entities.

原型面向对象编程语言比经典的面向对象编程语言简单得多,因为在原型面向对象编程中,我们只有一种抽象类型(即对象).例如,考虑:

Prototypal object-oriented programming languages are much simpler than classical object-oriented programming languages because in prototypal object-oriented programming we only have one type of abstraction (i.e. objects). For example, consider:

+----------------------+----------------+---------------------------------------+
| Level of Abstraction | Name of Entity |                Comments               |
+----------------------+----------------+---------------------------------------+
| 0                    | John Doe       | Real World Entity.                    |
| 1                    | johnDoe        | Variable holding object.              |
| 2                    | man            | Prototype of object johnDoe.          |
| 3                    | human          | Prototype of object man.              |
+----------------------+----------------+---------------------------------------+

正如您在原型面向对象编程语言中所见,对象是现实世界实体(在这种情况下,它们简称为对象)或其他对象(在这种情况下,它们被称为它们抽象的对象的原型)的抽象.因此,原型是一种概括.

As you can see in prototypal object-oriented programming languages objects are abstractions of either real world entities (in which case they are simply called objects) or other objects (in which case they are called prototypes of those objects that they abstract). Hence a prototype is a generalization.

原型面向对象编程语言中的对象可以是ex-nihilo(即从无到有)或从另一个对象(成为新创建对象的原型)创建的:

Objects in prototypal object-oriented programming languages may be created either ex-nihilo (i.e. out of nothing) or from another object (which becomes the prototype of the newly created object):

var human = {};
var man = Object.create(human);
var johnDoe = Object.create(man);

在我看来,原型面向对象编程语言比经典的面向对象编程语言更强大,因为:

In my humble opinion prototypal object-oriented programming languages are more powerful than classical object-oriented programming languages because:

  1. 只有一种抽象类型.
  2. 概括只是对象.

现在你一定已经意识到经典继承和原型继承的区别了.经典继承仅限于从其他类继承的类.但是原型继承不仅包括从其他原型继承的原型,还包括从原型继承的对象.

By now you must have realized the difference between classical inheritance and prototypal inheritance. Classical inheritance is limited to classes inheriting from other classes. However prototypal inheritance includes not only prototypes inheriting from other prototypes but also objects inheriting from prototypes.

您一定已经注意到原型和类非常相似.这是真的.他们是.事实上,它们非常相似,您实际上可以使用原型来为类建模:

You must have noticed that prototypes and classes are very similar. That's true. They are. In fact they are so similar that you can actually use prototypes to model classes:

function CLASS(base, body) {
    if (arguments.length < 2) body = base, base = Object.prototype;
    var prototype = Object.create(base, {new: {value: create}});
    return body.call(prototype, base), prototype;

    function create() {
        var self = Object.create(prototype);
        return prototype.hasOwnProperty("constructor") &&
            prototype.constructor.apply(self, arguments), self;
    }
}

使用上面的 CLASS 函数,您可以创建看起来像类的原型:

Using the above CLASS function you can create prototypes that look like classes:

var Human = CLASS(function () {
    var milliseconds = 1
      , seconds      = 1000 * milliseconds
      , minutes      = 60 * seconds
      , hours        = 60 * minutes
      , days         = 24 * hours
      , years        = 365.2425 * days;

    this.constructor = function (name, sex, dob) {
        this.name = name;
        this.sex = sex;
        this.dob = dob;
    };

    this.age = function () {
        return Math.floor((new Date - this.dob) / years);
    };
});

var Man = CLASS(Human, function (Human) {
    this.constructor = function (name, dob) {
        Human.constructor.call(this, name, "male", dob);
        if (this.age() < 18) throw new Error(name + " is a boy, not a man!");
    };
});

var johnDoe = Man.new("John Doe", new Date(1970, 0, 1));

然而,反过来却不是这样(即您不能使用类来建模原型).这是因为原型是对象而类不是对象.它们是完全不同类型的抽象.

The reverse is not true however (i.e. you can't use classes to model prototypes). This is because prototypes are objects but classes are not objects. They are an entirely different type of abstraction.

总而言之,我们了解到抽象是通过从特定示例中提取共同特征而形成的一般概念",而泛化是对更具体抽象的抽象"..我们还了解了原型继承和经典继承之间的区别,以及它们如何成为同一枚硬币的两张脸.

In summation we learned that an abstraction is a "a general concept formed by extracting common features from specific examples" and that generalization is "an abstraction of a more specific abstraction". We also learned about the differences between prototypal and classical inheritance and how both of them are two faces of the same coin.

在离别笔记中,我想指出原型继承有两种模式:原型模式和构造函数模式.原型模式是原型继承的规范模式,而构造函数模式用于使原型继承看起来更像经典继承.我个人更喜欢原型模式.

On a parting note I would like to remark that there are two patterns of prototypal inheritance: the prototypal pattern and the constructor pattern. The prototypal pattern is the canonical pattern of prototypal inheritance whereas the constructor pattern is used to make prototypal inheritance look more like classical inheritance. Personally I prefer the prototypal pattern.

这篇关于javascript中的经典继承与原型继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆