Javascript Duck打字的例子? [英] Example of Javascript Duck Typing?
问题描述
一些程序员建议不要在Javascript中使用伪经典继承,但建议使用duck-typing并为每个对象赋予一组功能。
Some programmers advise against using pseudo classical inheritance in Javascript, but advise using duck-typing and giving each object a set of capabilities.
是否有一个很好的例子怎么做的?我在下面有一个例子,但它一次只分配一个函数。我们可以为一个对象分配一组方法,例如我们可以设置 OceanAnimal
的原型,它可以游泳,潜水和上升,用于run,walk和jump的 LandAnimal
的原型,让一个对象从其中一个或两个继承? (所以fish对象可以继承或获得 OceanAnimal
的功能,而且一只乌龟可以获得 OceanAnimal
的功能和 LandAnimal
?)
Is there a good example of how that is done? I have an example down below, but it only assign function one at a time. Can we assign a whole group of methods to an object, such as can we set a prototype of OceanAnimal
which can "swim", "dive", and "rise", a prototype of LandAnimal
for "run", "walk", and "jump", and let an object inherit from one or both of them? (so a fish object can inherit or get the capabilities of OceanAnimal
, and a turtle can get the capabilities of both OceanAnimal
and LandAnimal
?)
var yoyo = {
name: "Yoyo",
type: "turtle"
}
var simba = {
name: "Simba",
type: "lion"
}
var dolphy = {
name: "Dolphy",
type: "dolphin"
}
function swim(n) {
console.log("My name is", this.name, ", I am a", this.type, "and I just swam", n, "feet")
}
function run(n) {
console.log("My name is", this.name, ", I am a", this.type, "and I just ran", n, "feet")
}
Object.prototype.respondTo = function(method) {
return !!(this[method] && (typeof this[method] === "function"));
}
yoyo.swim = swim;
yoyo.swim(10);
dolphy.swim = swim;
dolphy.swim(80);
simba.run = run;
simba.run(200);
yoyo.run = run;
yoyo.run(2);
yoyo.walk = run;
yoyo.walk(1);
console.log(simba.respondTo("swim"));
console.log(simba.respondTo("run"));
console.log(simba.respondTo("walk"));
console.log(yoyo.respondTo("run"));
console.log(yoyo.respondTo("walk"));
console.log(yoyo.respondTo("fly"));
if(dolphy.respondTo("run")) {
dolphy.run(10);
}
if(dolphy.respondTo("swim")) {
dolphy.swim(10);
}
输出:
My name is Yoyo , I am a turtle and I just swam 10 feet
My name is Dolphy , I am a dolphin and I just swam 80 feet
My name is Simba , I am a lion and I just ran 200 feet
My name is Yoyo , I am a turtle and I just ran 2 feet
My name is Yoyo , I am a turtle and I just ran 1 feet
false
true
false
true
true
false
My name is Dolphy , I am a dolphin and I just swam 10 feet
推荐答案
JavaScript中的函数是通用的。它们可以用作子程序,方法,构造函数,名称空间,模块等等。
Functions in JavaScript are versatile. They can be used as subroutines, methods, constructors, namespaces, modules, and much more.
人们建议不要在JavaScript中使用伪古典继承是因为它隐藏了JavaScript的真正威力。如果不是比对象更具表现力,那么函数就像表达一样。 Alonzo Church 的工作证明了这一点, Lambda Calculus ,图灵完成。
The reason people advise against using pseudo classical inheritance in JavaScript is because it hides the true power of JavaScript. Functions are just as expressive if not more expressive than objects. This has been proven by Alonzo Church who's work, Lambda Calculus, is Turing Complete.
要直接回答你的问题,我将使用函数创建一个 Turtle
,一个 Lion
和一个海豚
。然后我将演示一只乌龟是如何 OceanAnimal
和 LandAnimal
,狮子只是 LandAnimal
,以及海豚只是 OceanAnimal
。我将通过解释什么是鸭子打字来结束。
To answer your question directly I'll use functions to create a Turtle
, a Lion
and a Dolphin
. Then I'll demonstrate how a turtle is an OceanAnimal
and a LandAnimal
, how a lion is only a LandAnimal
, and how a dolphin is only an OceanAnimal
. I'll conclude by explaining what is duck typing.
首先让我们为 OceanAnimal
创建构造函数:
First let's create the constructor for an OceanAnimal
:
function OceanAnimal() {
this.swim = function (n) {
return "I am " + this.name + ", the " + this.type +
", and I just swam " + n + " meters.";
};
}
接下来我们将为 LandAnimal创建构造函数
:
function LandAnimal() {
this.walk = function (n) {
return "I am " + this.name + ", the " + this.type +
", and I just walked " + n + " meters.";
};
}
好的。所以现在让我们为 Turtle
创建构造函数:
Alright. So now let's create the constructor for a Turtle
:
Turtle.prototype.type = "turtle";
function Turtle(name) {
this.name = name;
LandAnimal.call(this);
OceanAnimal.call(this);
}
这里发生了什么?好的,我们希望 Turtle
继承 OceanAnimal
和 LandAnimal
。所以我们调用 LandAnimal.call(this)
和 OceanAnimal.call(this)
。通过这种方式,我们将 OceanAnimal
和 LandAnimal
构造函数用作mixins 的。因此 Turtle
继承自 OceanAnimal
和 LandAnimal
而实际上并没有成为类型 OceanAnimal
或 LandAnimal
。
What's happening here? Okay, we want Turtle
to inherit from both OceanAnimal
and LandAnimal
. So we're calling LandAnimal.call(this)
and OceanAnimal.call(this)
. In this way we're using the OceanAnimal
and LandAnimal
constructors as mixins. Thus Turtle
inherits from both OceanAnimal
and LandAnimal
without actually becoming of type OceanAnimal
or LandAnimal
.
另一件事是请注意,我们在 Turtle $ c> c $ c> c>上设置
而不是在里面。这是因为所有海龟的类型
属性类型
都是相同的。因此它是共享的。另一方面,每只乌龟的名称
可能会有所不同,因此它在构造函数中设置。
Another thing to notice is that we're setting the type
property on the prototype
of Turtle
instead of inside it. This is because type
is the same for all turtles. Thus it's shared. The name
of each turtle on the other hand may vary and hence it's set inside the constructor.
现在让我们同样为 Lion
创建构造函数:
Now let's similarly create the constructor for a Lion
:
Lion.prototype.type = "lion";
function Lion(name) {
this.name = name;
LandAnimal.call(this);
}
由于 Lion
是a LandAnimal
我们只混合 LandAnimal
构造函数。
Since Lion
is a LandAnimal
we only mix in the LandAnimal
constructor.
类似地,对于 Dolphin
:
Dolphin.prototype.type = "dolphin";
function Dolphin(name) {
this.name = name;
OceanAnimal.call(this);
}
现在我们已经创建了所有构造函数,让我们创建一只乌龟,一只狮子和海豚:
Now that we have created all the constructors let's create a turtle, a lion and a dolphin:
var yoyo = new Turtle("Yoyo");
var simba = new Lion("Simba");
var dolphy = new Dolphin("Dolphy");
Awww,现在让我们免费设置:
Awww, now let's set them free:
alert(yoyo.walk(10));
alert(yoyo.swim(30)); // turtles are faster in the water
alert(simba.walk(20));
alert(dolphy.swim(20));
哈哈。那很有趣。就个人而言,我最喜欢yoyo。
Haha. That was fun. Personally I love yoyo the most.
好的,那么什么是打字?我们知道yoyo是 OceanAnimal
和 LandAnimal
。但是,如果我们执行 yoyo instanceof OceanAnimal
或 yoyo instanceof LandAnimal
,则返回 false
。什么?
Okay, so what's duck typing? We know that yoyo is an OceanAnimal
and a LandAnimal
. However if we do yoyo instanceof OceanAnimal
or yoyo instanceof LandAnimal
then it returns false
. What?
- 你:愚蠢的JavaScript。
海龟
是OceanAnimal
和LandAnimal
! - JavaScript:不是我站在哪里。我所知道的是它是一个
海龟
。 - 你:但是如果它游了,那就是
OceanAnimal
,如果它走了,那么它是LandAnimal
。
- You: Stupid JavaScript. A
Turtle
is anOceanAnimal
and aLandAnimal
! - JavaScript: Not from where I'm standing. All I know is that it's a
Turtle
. - You: But if it swims then it's an
OceanAnimal
, and if it walks then it's aLandAnimal
.
因为JavaScript是这样的派对,所以我们必须创建自己的测试来检查对象是否是 OceanAnimal
,如果是a LandAnimal
。
So since JavaScript is such a party pooper we'll have to create our own test to check if an object is an OceanAnimal
and if it's a LandAnimal
.
让我们从 OceanAnimal
开始:
function isOceanAnimal(object) {
if (typeof object !== "object") return false;
if (typeof object.swim !== "function") return false;
return true;
}
类似地,对于 LandAnimal
:
function isLandAnimal(object) {
if (typeof object !== "object") return false;
if (typeof object.walk !== "function") return false;
return true;
}
现在我们可以使用 isOceanAnimal(yoyo)
而不是 yoyo instanceof OceanAnimal
和 isLandAnimal(yoyo)
而不是 yoyo instanceof LandAnimal
;这两个函数都会为我们心爱的yoyo返回 true
。 Yay!
So now we can use isOceanAnimal(yoyo)
instead of yoyo instanceof OceanAnimal
, and isLandAnimal(yoyo)
instead of yoyo instanceof LandAnimal
; and both these functions will return true
for our beloved yoyo. Yay!
这是一个用JavaScript输入鸭子的简单例子。总结:
This is a simple example of duck typing in JavaScript. To conclude:
当我看到一只像鸭子一样散步的小鸟,像鸭子一样游泳,像鸭子一样嘎嘎叫时,我叫那只小鸟一只鸭子。
When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.
同样:
当我看到一种像海洋动物一样游动的动物时,我称这种动物为海洋动物;当我看到一只像陆地动物一样行走的动物时,我称这种动物为陆地动物。
When I see an animal which swims like an ocean animal, I call that animal an ocean animal; and when I see an animal which walks like a land animal, I call that animal a land animal.
编辑:您可以在此处查看以上代码: http://jsfiddle.net/aaditmshah/X9M4G/
You can see the above code in action here: http://jsfiddle.net/aaditmshah/X9M4G/
这篇关于Javascript Duck打字的例子?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!