Javascript“抽象方法”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15305938/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 00:17:28  来源:igfitidea点击:

Javascript "abstract method"

javascriptjqueryoopoverloadingobject-literal

提问by orange

My terminology is a bit off, so feel free to correct where necessary. I want to overload a function in javascript and the 'base class' to make use of the overloaded method as well as the inherited class to access the base classes methods. So far, I came up with a (working) mix of jquery.extend()and object literals, but this doesn't look pretty. I was wondering if there's a better way of doing this (can use jquery).

我的术语有点不对,所以请随时在必要时更正。我想在 javascript 和“基类”中重载一个函数,以利用重载的方法以及继承的类来访问基类方法。到目前为止,我想出了一个(工作)混合jquery.extend()和对象文字,但这看起来并不漂亮。我想知道是否有更好的方法来做到这一点(可以使用 jquery)。

var Base = new function(args, m) {
   $.extend(this, m);
   var self = this;
   this.bar = function() {
     self.foo();
   }
   this.foo = function() {
     self.blah();
   }
   this.dosomething = function() {}
};

var Child = function(arg1) {
   $.extend(this, new Base(args, {
     blah: function() {
       self.dosomething()
     }
   }));
}

回答by Benjamin Gruenbaum

What you're looking for is a way to share functionality across objects. This is exactlythe sort of thing the JavaScript prototypical inheritance model excels at.

您正在寻找的是一种跨对象共享功能的方法。这正是JavaScript 原型继承模型所擅长的。

There's no need to use jQuery or other libraries in order to accomplish this. Consider going withthe language's way of doing things.

无需使用 jQuery 或其他库来完成此操作。考虑采用语言的做事方式。

Prototypes

原型

In JavaScript, objects have 'prototypes'. When JavaScript looks for a method in an object that does not have it, it looks for it up on the prototype 'chain'. So all you need to do is override that functionality at a lower level on that chain.

在 JavaScript 中,对象具有“原型”。当 JavaScript 在一个没有它的对象中寻找一个方法时,它会在原型“链”上寻找它。因此,您需要做的就是在该链的较低级别覆盖该功能。

This is explained in detail in the tutorial about it on MDN.

在 MDN 上的教程中有详细解释

Your specific case

您的具体情况

If I want a Baseand Childclass, where the Basehas a method that Childneeds to override, all we need to do is assign it anywhere lower in that chain.

如果我想要一个BaseChild类,其中Base有一个Child需要覆盖的方法,我们需要做的就是将它分配给该链中较低的任何位置。

The order of look-up is

查找顺序是

Child Object --> Child's prototype (a Base object) --> Base's prototype (an Object)

For example, let's say you have a class Base

例如,假设您有一个 Base 类

function Base(){

}
Base.prototype.bar = function() {
     //bar logic here
     console.log("Hello");
};
Base.prototype.foo= function() {
     //foo logic here
};

Function Child(){

}

Child.prototype = new Base();

I'd like Child to implement Bar differently, in which case I can do

我希望 Child 以不同的方式实现 Bar,在这种情况下我可以做到

Child.prototype.bar = function(){
   console.log("World");
}

Which results in

这导致

var a = new Base();
a.bar(); //outputs "Hello" to the console
var b = new Child();
b.bar(); //outputs "World" to the console
         //The Base instance that is the prototype of b has the bar method changed above

Note On Abstract Classes in JavaScript

JavaScript 中抽象类的注意事项

Two of the primary reasons abstract methods inheritance is used in languages that are based on classical inheritance (like Java) is Polymorphism and code sharing.

在基于经典继承的语言(如 Java)中使用抽象方法继承的两个主要原因是多态性和代码共享。

In JavaScript neither are a problem. Code sharing can be done using prototypical inheritance just as easily. Moreoever, you can take just about any function and run it in another context. For example, I can even call the barmethod of a Childobject on an empty array by doing b.bar.call([]).

在 JavaScript 中,两者都不是问题。使用原型继承也可以轻松实现代码共享。此外,您几乎可以使用任何函数并在另一个上下文中运行它。例如,我甚至可以调用bar一个方法Child通过执行一个空数组上对象b.bar.call([])

As for polymorphism JavaScript is a dynamic language with duck typing. This means it looks at objects based on their ability and not the way they were declared. If several objects have a method called barI would have no problemcalling that method on each of them if they are in an array or other collection. In Java that would require a common interface,type or ancestor.

至于多态性,JavaScript 是一种带有鸭子类型的动态语言。这意味着它根据对象的能力而不是它们的声明方式来查看对象。如果几个对象有一个方法叫bar我本来没有问题,呼吁他们每个人的这种方法,如果他们是在一个阵列或其他集合。在 Java 中,这将需要一个公共接口、类型或祖先。

For these reasons, things like abstract classesdon't play a big role in JavaScript.

由于这些原因,抽象类之类的东西在 JavaScript 中并没有发挥重要作用。

回答by Brigand

I recommend doing it the way CoffeeScriptdoes it. You can put the first vardeclaration in a separate file to keep the code looking nice. As far as I know __extendsis equivalent to $.extends

我建议按照CoffeeScript的方式来做。您可以将第一个var声明放在一个单独的文件中,以使代码看起来不错。据我所知__extends相当于$.extends

var __hasProp = {}.hasOwnProperty,
  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };


var Fruit = (function() {

  function Fruit() {
    console.log("New fruit");
  }

  return Fruit;

})();

var Apple = (function(_super) {

  __extends(Apple, _super);

  function Apple() {
    console.log("New apple");
    Apple.__super__.constructor.apply(this, arguments);
  }

  return Apple;

})(Fruit);

var apple = new Apple();

Or, if you can use CoffeeScript, it looks like this:

或者,如果您可以使用 CoffeeScript,它看起来像这样:

class Fruit
  constructor: ->
    console.log "New fruit"

class Apple extends Fruit
  constructor: ->
    console.log "New apple"
    super