JavaScript多态变量继承

3

我正在JavaScript中练习多态(第一次尝试),根据我在网上找到的不同示例。我知道在其他语言中,我可以从扩展类中访问超类的变量,并想知道如何在JavaScript中正确地执行此操作。下面的代码没有抛出任何错误(至少就Firefox的错误控制台而言),但是ExtendedClass中的statement未定义。

function MyClass() {
  this.statement = "I'm a class with a method";
  this.speak = function() {
    alert(this.statement);
  }
}
var mInstance = new MyClass();
mInstance.speak();

function ExtendedClass() {
  Object.create(MyClass);
  this.speak = function() {
    alert(this.statement+" and I extend a class");
  }
}
var eInstance = new ExtendedClass();
eInstance.speak();

我能否从ExtendedClass访问statement?这是实现多态的好方法吗?
3个回答

2
您可以使用 MyClass.call(this) 来设置本地变量,然后使用 Object.create 设置原型,像这样:
function MyClass() {
  this.statement = "I'm a class with a method";
  this.speak = function() {
    alert(this.statement);
  }
}
var mInstance = new MyClass();
mInstance.speak();

function ExtendedClass() {
  MyClass.call(this);
  this.speak = function() {
    alert(this.statement+" and I extend a class");
  }
}
ExtendedClass.prototype = Object.create(MyClass.prototype);
var eInstance = new ExtendedClass();
eInstance.speak();

您可以在MDN文档中了解更多相关IT技术。


这看起来就像RyanFishman的答案,但它还有ExtendedClass.prototype = Object.create(MyClass.prototype);,那是什么意思?我不习惯使用prototypeObject.create() - asimes
是的,我们同时发布了。这篇文章可能会给出一个长的解释:http://www.benmccormick.org/blog/2013/01/12/javascript-explained-object-oriented-javascript/,但简短的解释是JavaScript继承的工作方式与经典继承不同。对象具有可以与其他对象共享的“原型链”。所有对象默认共享Object.prototype原型,并且它们还可以共享其他对象的原型,如上所示。我链接的MDN文章也解释了这一点。 - Ben McCormick
啊,抱歉,我应该用不同的措辞表达,我并不是想暗示你在看到他的回答后才写下你的答案。谢谢。 - asimes
只是双重检查,额外的一行是为了纠正ExtendedClass的构造函数指针吗? - asimes
不完全是。函数ExtendedClass()是ExtendedClass类型的构造函数。ExtendedCLass.prototype是对ExtendedClass类型原型链的引用,这就是JavaScript中控制继承的方式。在像JavaScript或C++这样的语言中,它没有确切的等价物,因为这些语言使用的是经典继承而不是原型继承。 - Ben McCormick

1

我是这样做的

function MyClass() {
  this.statement = "I'm a class with a method";
  this.speak = function() {
    alert(this.statement);
  }
}
var mInstance = new MyClass();
mInstance.speak();

function ExtendedClass() {
  MyClass.call(this);
  this.speak = function() {
    alert(this.statement+" and I extend a class");
  }
}
var eInstance = new ExtendedClass();
eInstance.speak();

我不确定这是否是最佳的语法,但我知道这可以工作,并且您可以正确继承MyClass及其所有公共方法和变量。


1

原型是您正在寻找的。

var MyClass = function(){}; //Empty Constructor
MyClass.prototype = {
    statement: "I'm a class with a method",
    speak: function(){
        alert(this.statement);
    }
};
var ExtendedClass = function(){}; //Empty Constructor
ExtendedClass.prototype = new MyClass();
ExtendedClass.prototype.speak = function(){
    alert(this.statement+" and I extend a class");
};
var eInstance = new ExtendedClass();
eInstance.speak();

иҝҷжҳҜеҲӣе»әExtendedClassзҡ„еҸҰдёҖз§Қж–№ејҸеҗ—пјҹд»ҺжҲ‘жүҖзҹҘйҒ“зҡ„иҜӯиЁҖдёӯпјҢиҜӯжі•зңӢиө·жқҘдёҚеғҸзұ»еЈ°жҳҺгҖӮ - asimes
是的,JavaScript的面向对象编程和继承方式非传统(委婉地说)。这是我能够做到的最简洁的描述,而不使用call方法。不确定为什么,我只是从来不喜欢使用方法来实际继承其他对象的属性和方法。这归结于你个人的喜好以及对代码可读性的理解。 - maiorano84
我刚尝试复制/粘贴此内容以尝试它,因为它看起来与其他内容非常不同,但是它会抛出一个错误:_MyClass未定义_。 - asimes
抱歉,我忘了在原始代码中定义实际对象。现已更新为经过测试的工作示例。 - maiorano84
1
感谢您修复它。我认为我暂时会坚持使用看起来像Java的那些,但看到更多的例子很好。 - asimes
这是最好的选择。无论对你来说哪种方式最易读和易识别。当你习惯了通常的面向对象编程风格时,Javascript往往会对此造成干扰。 - maiorano84

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接