【问题标题】:How to use polymorphism in Javascript如何在 Javascript 中使用多态性
【发布时间】:2016-10-31 09:55:15
【问题描述】:

大多数语言对类使用单继承。这样做的模式相当明显(例如在下面的 Swift 代码中)。我仍在尝试围绕 JavaScript 中的模式来创建对象层次结构并重用类函数并覆盖类函数

class animal {
    func talk() {
        print ("?")
    }
}

class bird : animal {
    override func talk() {
        print("tweet tweet")
    }
    func fly() {
        print("flap flap")
    }
}

class parrot : bird {
    override func talk() {
        print("polly want a cracker")
    }
}

var a = animal()
var b = bird()
var p = parrot()

a.talk()  /// ?
b.talk()  /// tweet tweet
b.fly()   /// flap flap
p.talk()  /// polly want a cracker
p.fly()   /// flap flap

我认为我的问题是 Javascript 代码看起来不像这样。什么是等效的 Javascript 代码,以便我找出模式?

【问题讨论】:

  • 好吧,不是 nitpik,而是这个问题与问题的“是什么”部分混杂在一起。我没有问题,只需要对“如何”进行干净的一对一比较来转换它。

标签: javascript inheritance polymorphism


【解决方案1】:

您几乎回答了自己的问题。你只需要学习 JavaScript 的语法。

我认为我的问题是 Javascript 代码看起来不像这样。

  1. 如果一种语言看起来与另一种不同,这对您来说不是“问题”

  2. 您提供的 Swift 代码在语法上非常接近您需要编写的 JavaScript (ES6) 以表达相同的类层次结构

class Animal {
  talk() {
    console.log('?')
  }
}

class Bird extends Animal {
  talk() {
    console.log('tweet tweet')
  }
  fly() {
    console.log('flap flap')
  }
}

class Parrot extends Bird {
  talk() {
    console.log('polly want a cracker')
  }
}

var a = new Animal()
var b = new Bird()
var p = new Parrot()

a.talk()
b.talk()
b.fly()
p.talk()
p.fly()

如果你想在 ES5 中设置一个“类”继承,你可以这样做

// Animal "class"
function Animal() {}

// Animal methods
Animal.prototype.talk = function talk() {
  console.log('?')
}

// ------------------------------
// Bird "class"
function Bird() {
  // if you want to call the parent constructor, you can do that here
  // Animal.call(this, arg1, arg2, ... argN)
}

// Bird inherits from Animal
Bird.prototype = Object.create(Animal.prototype)
Bird.prototype.constructor = Bird

// Bird methods
Bird.prototype.talk = function() {
  console.log('tweet tweet')
}
Bird.prototype.fly = function() {
  console.log('flap flap')
}

// ------------------------------
// Parrot "class"
function Parrot() {
  // if you want to call the parent constructor, you can do that here
  // Bird.call(this, arg1, arg2, ... argN)
}

// Parrot inherits from Bird
Parrot.prototype = Object.create(Bird.prototype)
Parrot.prototype.constructor = Parrot

// Parrot methods
Parrot.prototype.talk = function() {
  console.log('polly want a cracker')
}

var a = new Animal()
var b = new Bird()
var p = new Parrot()

a.talk()
b.talk()
b.fly()
p.talk()
p.fly()

【讨论】:

  • 我认为 Javascript 不支持“class”关键字?
  • ES6 支持 class 关键字。它是一种语法糖,完全相同的代码可以在 ES5 或更低版本中表示。
  • 谢谢。正是我需要的。顺便说一句,所谓的重复问题的答案甚至没有提到 ES6 方式,这就是我所追求的。
  • @naomik 所以基本上talk() 动物的方法在鸟和鹦鹉中被覆盖了?
  • @naomik 我们也可以重载吗?
【解决方案2】:

有两个答案,ES6:

class animal {
    talk() {
        console.log("?")
    }
}

class bird extends animal {
    talk() {
        console.log("tweet tweet")
    }
    fly() {
        console.log("flap flap")
    }
}

class parrot extends bird {
    talk() {
        console.log("polly want a cracker")
    }
}

var a = new animal()
var b = new bird()
var p = new parrot()

a.talk()  /// ?
b.talk()  /// tweet tweet
b.fly()   /// flap flap
p.talk()  /// polly want a cracker
p.fly()   /// flap flap

和 ES5:

function animal() {

}

animal.prototype.talk = function () {
    console.log("?")
};

function bird() {
    animal.call(this)
}

bird.prototype = Object.create(
    animal.prototype,
    {constructor: {value: bird}}
);

bird.prototype.talk = function () {
    console.log("tweet tweet")
};

bird.prototype.fly = function () {
    console.log("flap flap")
};

function parrot() {
    bird.call(this);
}

parrot.prototype = Object.create(
    bird.prototype,
    {constructor: {value: parrot}}
);

parrot.prototype.talk = function () {
    console.log("polly want a cracker")
};


var a = new animal()
var b = new bird()
var p = new parrot()

a.talk()  /// ?
b.talk()  /// tweet tweet
b.fly()   /// flap flap
p.talk()  /// polly want a cracker
p.fly()   /// flap flap

【讨论】:

  • bird.call(this) 在做什么?
  • 它正在调用鸟的构造函数来使鹦鹉实例将自己初始化为鸟。如果鸟构造函数或动物构造函数中有任何内容,则会执行。
  • 感谢您的回复。还有一个快速的问题。为什么我们必须像{constructor: {value: parrot} 那样将构造函数指向parrot?如果我们不这样做会怎样?
  • 如果你不这样做,它通常并不重要,但它会导致 parrot.prototype.constructor === 鸟。这不会导致 new parrot() 只创建一只鸟,所以这没什么大不了的,但是 ES5 语法的重点是几乎准确地显示 ES6 语法正在做什么,除了一些技术,否则会使代码完全不可读(比如让每个原型方法都像 ES6 类一样不可枚举)
猜你喜欢
  • 2015-07-22
  • 1970-01-01
  • 2012-04-08
  • 2013-04-10
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
  • 2012-03-06
  • 2017-01-01
相关资源
最近更新 更多