【问题标题】:Understanding the difference between classical and prototypal inheritance了解经典继承和原型继承之间的区别
【发布时间】:2016-07-30 19:48:35
【问题描述】:

在过去的一周里,我一直在尝试了解基于类的继承和原型继承之间的区别。在使用过 PHP 和 JavaScript 之后,我希望能很快掌握这一点,但我无法完全理解这一点——我总觉得我错过了一些东西。

我了解到,类就像定义对象特征的蓝图。当一个类被实例化时,根据蓝图构造一个对象。当继承发挥作用时,只能完全采用蓝图,但可以覆盖方法。

但是什么是原型呢?它不是也类似蓝图,但已经实现(因此名称为“原型”)?那么通过继承,你只能指向已经存在的函数?

以下内容可能看起来很愚蠢,但这就是我试图理解事物的方式。

在更人性化的方面:一个类可以被视为架构计划,一旦它被实例化,小工人就开始根据该计划构建一个对象。为了继承某些东西,除了新的细节(可能会替换现有的细节)之外,还要重新构建完整的计划。

使用原型,工人开始复制已经存在的对象并开始查看它的主要特征(存储在称为原型的东西上)。要从另一个对象继承,他们只需在某处放置一个标志,上面写着“您正在寻找函数 X?请这样——注意对象之间的间隙”。

这种区分正确吗?

【问题讨论】:

标签: javascript prototype


【解决方案1】:

在我看来,你实际上已经明白了。

基于类的 OO

正如您已经提到的,在基于类的面向对象语言(如 Java)中,类是每个未来对象的蓝图。对于对象的实例化,蓝图(您创建的类)被复制为该对象。这意味着,如果您在实例化对象后更改类,则先前创建的对象不会有该更改。

说到继承:假设你有一个 Person 类。您想创建另一个继承自 Person 的 Student 类。 Student 基本上是蓝图 Person 的一个副本,可以扩展蓝图的功能。所以你的例子非常准确! 这在复杂但相当静态的 OO 结构中非常有用!

基于原型

JavaScript 等基于原型的语言不遵循这种模板方法。你的例子再次打得很好。您基本上只是创建一个对象并引用另一个对象(您的原型)。您放入原型中的所有功能都将由引用该原型对象的所有对象共享。但是,重要的是要了解您不会复制蓝图或模板。你总是在处理对象。

所以你可以创建一个 Person 对象。这包含像“sayHello”这样的方法。如果您创建具体的人,例如乔,您只需创建另一个对象并将其链接到 Person 对象。因此,如果您尝试 Joe.sayHello(),它将查看 Joe 对象的属性并且找不到 sayHello 方法,因此它将跳转到具体的 Person 对象。就像你用你的例子说的那样。

我不太喜欢基于原型的语言中的表达式继承,因为它实际上并不存在。您无需复制蓝图并扩展其功能。继承基本上是通过将对象链接在一起来工作的。比如上面的例子。你可以有一个 Person 对象。每个普通人对象(例如 Joe)都有 Person 对象作为原型。现在您创建一个以 Person 作为原型的 Student 对象。另一个对象(例如 StudentJoe)可以将 Student 作为原型。所以它可以通过链一直到人来访问它的方法。 简而言之;):基于原型的语言仅适用于链接在一起的具体对象(原型),而不适用于蓝图和模板。 这种方法的优点是动态的(这就是这种方法在网络中常用的原因)。由于您从不使用模板,而是使用具体对象,因此原型链中的每次更改都会对每个对象产生影响(就可访问功能而言)——无论它是何时创建的。

我希望这会有所帮助。有一本好书叫You dont know JavaScript - this & object prototype,它很好地解释了这个基于 JavaScript 的主题。

【讨论】:

  • 这确实有帮助!谢谢,我现在比以前更有信心了。
  • 这种解释在无数博客文章、文章和问答中脱颖而出,它们大多回避了实际差异的问题。谢谢。
猜你喜欢
  • 1970-01-01
  • 2013-11-07
  • 2011-02-17
  • 2020-10-03
  • 2016-10-31
  • 1970-01-01
  • 2010-10-26
相关资源
最近更新 更多