任何人都可以帮助您使用以下代码。我试图理解多重继承不确定为什么它不起作用。 BTW如果是多重继承的代码。谢谢
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Test Doc</title>
<script type="text/javascript">
function classX(){
this.messageX="this is X Message";
this.alertX=function(){
alert(this.messageX);
};
}
function classY(){
this.messageY="this is Y Message";
this.alertY=function(){
alert(this.messageY);
};
}
function classZ(){
classX.apply(this);
classY.apply(this);
this.messageZ="this is Z Message";
this.alertZ=function(){
alert(this.messageZ);
};
}
var abjz=new classZ();
objz.alertZ();
abjz.alertX();
</script>
</head>
<body>
</body>
</html>
答案 0 :(得分:16)
JavaSript没有真正的多重继承。您只能从一个原型继承,然后复制所需的其余属性。您可以使用instanceof
运算符对此进行测试。
在修复错误拼写之后,你的演示工作,但实际上,你并没有真正继承。要做真正的JS继承:
function A(){}
function B(){}
B.prototype = new A;
b = new B;
console.log(b instanceof A, b instanceof B);
//-> true, true
的更多信息
function ctorX() {
this.messageX = "this is X Message";
this.alertX = function() {
console.log(this.messageX);
};
}
function ctorY() {
this.messageY = "this is Y Message";
this.alertY = function() {
console.log(this.messageY);
};
}
function ctorZ() {
ctorX.call(this); // This is the quasi-multiple inheritance
this.messageZ = "this is Z Message";
this.alertZ = function() {
console.log(this.messageZ);
};
}
ctorZ.prototype = new ctorY; // This is the actual inheritance
var objz = new ctorZ();
objz.alertZ();
objz.alertY();
objz.alertX();
console.assert(objz instanceof ctorZ, 'objz is not instance of ctorZ');
console.assert(objz instanceof ctorY, 'objz is not instance of ctorY');
console.assert(objz instanceof ctorX, 'objz is not instance of ctorX');
//The last assert will fail since there is no true multiple inheritance
HMR提出了一个观点,即在某些情况下,用户想要从特定的构造函数继承,但是超级构造函数需要参数并且将失败。绕过这个的方法是创建一个代理构造函数:
function C(x){if(!x) throw new Error;}
function D(){}
function proxyCtor(){/*should be noop*/}
proxyCtor.prototype = C.prototype;
D.prototype = new proxyCtor;
var d = new D;
console.assert(d instanceof C, 'c is not instance of D');
// will err if incorrect, which it's not
答案 1 :(得分:6)
你在“alertZ()”的调用中错误拼写了“abjz”。
经过更正,代码工作正常,据我所知(两个警报显示,一个用于Z,一个用于X)。
答案 2 :(得分:1)
您的代码不会导致classZ继承classX和classY,它只会复制其属性/方法。
Object.getOwnPropertyNames(abjz)
揭示了: -
messageX,alertX,messageY,alertY,messageZ,alertZ
但是对于继承,您希望警报方法仅保留在各自的类中,以便对它们的任何更改将在稍后的abjz中反映出来。此外,如果您创建更多像abjz这样的实例,那么就不会出现方法维护问题。
你可以这样做: -
var classX = {}
classX.messageX = "this is X Message"
classX.alertX = function(){
alert(this.messageX)
}
var classY = Object.create(classX)
classY.messageY = "this is Y Message"
classY.alertY = function(){
alert(this.messageY)
}
var classZ = Object.create(classY)
classZ.messageZ = "this is Z Message"
classZ.alertZ = function(){
alert(this.messageZ)
}
var abjz = Object.create(classZ)
相当于: -
function classX(){}
classX.prototype.messageX = "this is X Message"
classX.prototype.alertX = function(){
alert(this.messageX)
}
function classY(){}
classY.prototype = classX.prototype
classY.prototype.messageY = "this is Y Message"
classY.prototype.alertY = function(){
alert(this.messageY)
}
function classZ(){}
classZ.prototype = classY.prototype
classZ.prototype.messageZ = "this is Z Message"
classZ.prototype.alertZ = function(){
alert(this.messageZ)
}
var abjz = new classZ()
两者都应输出: -
alert( Object.getOwnPropertyNames(abjz) ) //
abjz.alertX() // this is X Message
abjz.alertY() // this is Y Message
abjz.alertZ() // this is Z Message
所以现在abjz继承自classZ,它继承自classY,类似于线性原型链中的classX: -
abjz --> classZ --> classY --> classX
但这不是多重继承。为此,abjz需要直接从classX,classY和classZ继承而没有链,即
abjz --> classZ
abjz --> classY
abjz --> classX
不幸的是,JS原型链系统不允许这样做,并且多重继承的灵活优势被有序原型链所扼杀。例如,如果您还希望实例cdef仅从classZ和classX继承: -
cdef --> classZ --> classX
然后在JS中,classZ原型必须从classY更改为classX并且会混淆abjz实例。而在多重继承中: -
cdef --> classZ
cdef --> classX
classZ仍然很好,因为没有尴尬的链条来处理。
答案 3 :(得分:1)
您可以通过在多继承树中的所有链中创建代理(总共树)来创建代理,然后展平此树并将预先排序的所有这些代理原型链接起来DFS遍历。然后,您必须在继承树中的每个构造函数上更新[Symbol.hasInstance],以表明此构造函数确实具有此实例。我在这里工作:https://github.com/dosaygo-coder-0/postjs/blob/master/posttypes/src/mixOf.js
目前(2016年10月12日),上述想法尚未完全实施。
答案 4 :(得分:0)
JavaScript无法直接访问多重继承。
要使用它,您可以使用允许多重继承的类系统,如Ring.js。
答案 5 :(得分:0)
试试这个简化多重继承的库:https://github.com/meddler/inherit(参见:https://github.com/meddler/inherit/blob/master/test/module/inherit/from.js#L19)
答案 6 :(得分:0)
在Basarat Syed的Beginning Node.js一书中,他展示了一种继承模式。此代码演示了他设置原型链的方法。它使用util模块作为链接原型链的帮助器。
从第91页开始,“Javascript支持原型继承。他的书的第2章解释了原型是如何工作的。在JavaScript中,会查找当前项目的成员(例如item.foo),然后是其原型(item。 proto .foo),然后是原型的原型(item。 proto 。 proto .foo),依此类推,直到原型本身(例如,item。 proto 。 proto 。 proto )为空。“ - Basarat Syed
注意:堆栈溢出编辑器从proto。
中删除了“__”前缀和后缀示例代码。基类是Animal,Bird类派生自Animal,而超人类派生自Bird。
var inherits = require('util').inherits;
// Animal class, the parent
function Animal(name){
this.name = name;
// Additional initialization code
}
Animal.prototype.walk = function(destination){
console.log(this.name,'is walking to',destination);
}
Animal.prototype.eat = function(food){
console.log(this.name,'is eating',food);
}
// Bird class, child of Animal
function Bird(name){
// call the Animal constructor
Animal.call(this,name);
// Additional initialization code
}
Bird.prototype.fly = function(destination){
console.log(this.name,'is flying to',destination);
}
// Setup the prototype chain from child Bird to parent Animal
inherits(Bird,Animal);
// Superman class, child of Bird
function Superman(name){
// Call the Bird constructor
Bird.call(this,name);
// Additional initialization code
}
Superman.prototype.jump = function(destination){
console.log(this.name,'jumped over a',destination);
}
// Setup the prototype chain from child Superman to parent Bird
inherits(Superman,Bird);
// Create the parent instance
var animal = new Animal('elephant');
animal.walk('melbourne');
animal.eat('grass');
// Create the child of animal instance
var bird = new Bird('sparrow');
bird.walk('sydney');
bird.fly('melbourne');
bird.eat('seeds');
// Create the child of bird instance
var superman = new Superman('Clark Kent');
superman.fly('Gotham');
superman.walk('Daily planet');
superman.jump('Building');
superman.eat('Hot dogs');
输出:
大象正走向墨尔本 大象正在吃草 麻雀正走向悉尼 麻雀飞向墨尔本 麻雀正在吃种子 克拉克肯特飞往哥谭 克拉克肯特走到每日星球上 克拉克肯特跳过一幢建筑物 克拉克肯特正在吃热狗