经典的inheritance与原生的inheritance在JavaScript中

我已经search了很多链接,无法理解经典inheritance和原型inheritance之间的区别。

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

  • 原型inheritance优于古典?

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

古典inheritance

// 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); 

古典inheritance里面使用原型inheritance吗?

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

从上面的链接,我知道我们不能在运行时添加新的方法在经典的inheritance 。 它是否正确? 但是你可以检查上面的代码, 我可以通过原型在运行时添加“移动”方法和任何方法 。 那么这是基于古典inheritance的原型吗? 如果那么实际的古典inheritance和原型inheritance是什么? 我对此感到困惑。

原型inheritance。

 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); 

这是类似于古典inheritance? 我完全不知道什么是原型inheritance? 什么是古典inheritance? 为什么古典传承不好?

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

谢谢,

湿婆

您在问题中演示的代码示例都使用原型inheritance。 实际上,您用JavaScript编写的任何面向对象的代码都是原型inheritance的范例。 JavaScript根本就没有经典的inheritance。 这应该清楚一点:

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

正如你所看到的,原型inheritance和经典inheritance是两种不同的inheritance范式。 像Self,Lua和JavaScript等语言支持原型inheritance。 然而,像C ++,Java和C#这样的大多数语言都支持经典的inheritance。


面向对象编程的快速概述

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

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

理论上抽象被定义为“通过从具体例子中提取共同特征而形成的一般概念”。 但是为了解释这个,我们将使用前面提到的定义。

现在有些物体有很多共同点。 比如泥巴车和哈雷戴维森有很多共同之处。

泥地车:

泥地车。

哈雷戴维森:

哈雷戴维森

泥自行车和哈雷戴维森都是自行车。 因此,一辆自行车是一个泥自行车和哈雷戴维森泛化。

  Bike | +---------------------------------+ | | vv Mud Bike Harley Davidson 

在上面的例子中,自行车,泥地车和哈雷戴维森都是抽象的。 然而,自行车是一个更普遍的泥自行车和哈雷戴维森(即泥自行车和哈雷戴维森是特定types的自行车)的抽象。

泛化:更具体抽象的抽象。

在面向对象编程中,我们创build对象(抽象为真实世界的实体),我们使用类或原型来创build这些对象的概括。 泛化是通过inheritance来创build的。 一辆自行车是泥浆自行车的概括。 因此泥自行车inheritance自行车。


经典的面向对象编程

在经典的面向对象编程中,我们有两种types的抽象:类和对象。 如前所述,一个对象是一个真实世界实体的抽象。 另一方面,类是对象或其他类的抽象(即泛化)。 例如,考虑:

 +----------------------+----------------+---------------------------------------+ | 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)。

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

 class Human { // ... } class Man extends Human { // ... } Man johnDoe = new Man(); 

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

因此,随着抽象程度的增加,实体变得更加普遍,随着抽象程度的降低,实体变得更为具体。 在这个意义上,抽象的程度类似于从更具体的实体到更一般的实体的范围。


原型面向对象编程

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

 +----------------------+----------------+---------------------------------------+ | 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. | +----------------------+----------------+---------------------------------------+ 

正如您在原型面向对象编程语言中所看到的,对象是现实世界实体(在这种情况下,它们简称为对象)或其他对象(在这种情况下称为它们抽象的对象的原型)的抽象。 因此原型是一个泛化。

原型面向对象编程语言中的对象可能是由ex-nihilo(即无所有)或另一个对象(它成为新创build对象的原型)创build的:

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

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

  1. 只有一种抽象。
  2. 泛化只是对象。

现在你一定意识到了经典遗传和原型遗传的区别。 古典inheritance仅限于从其他类inheritance的类。 然而,原型inheritance不仅包括从其他原型inheritance的原型,还包括从原型inheritance的对象。


原型级同构

你一定注意到原型和类非常相似。 确实如此。 他们是。 事实上,它们非常相似,以至于你实际上可以使用原型来build模:

 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函数,你可以创build看起来像类的原型:

 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)); 

然而事实并非如此(即你不能用类来模拟原型)。 这是因为原型是对象,但类不是对象。 它们是完全不同的抽象types。


结论

总而言之,我们了解到抽象是“从具体例子中提取共同特征形成的一般概念” ,泛化是“更具体抽象的抽象” 。 我们也了解了原型遗传和古典遗传之间的区别,以及它们是如何同一枚硬币的两面。

在备忘录中,我想说的是原型inheritance有两种模式:原型模式和构造模式。 原型模式是原型inheritance的规范模式,而构造模式用于使原型inheritance看起来更像经典inheritance。 我个人更喜欢原型模式。

PS我是写博客文章“ 为什么原型inheritance问题 ”的人,回答了“ 原型inheritance优于古典? ”的问题。 我的答案是接受的答案。