[英]Why Javascript does not support inheritance by default?
从OOPS基础开始,我总是使用继承作为代码重用的强大工具,
例如,如果我在OOPS中写一个国际象棋程序,当我实现一个is-a
关系时,
Class Piece{
int teamColor;
bool isLive;
Positon pos;
int Points;
.......
int getTeamColor(){....}
.......
};
Class Rook extend Piece{ //`is-a`
...... // No getTeamColor() definition here.. because the parent has the definition.
};
Class Pawn extend Piece{ //`is-a`
......// No getTeamColor() definition here.. because the parent has the definition.
};
我可以用javascript中的has-a
关系来做到这一点,但我看到的缺点是,我必须重新定义派生类中的每个函数。
示例:在每个车,骑士,典当,国王......等中再次重新定义getTeamColor()。
var Pawn = function(teamColor,pos){
var piece = new Piece(teamColor,pos);
.......
this.getTeamColor = function(){
return piece.getTeamColor();
};
}
我的问题是,为什么javascript不支持经典继承作为默认选项?
[2018年更新]现在,JavaScript显然支持使用本机语言功能进行继承。
class A { }
class B extends A { }
[/更新]
JavaScript确实支持原型方式的继承。 你需要的不是类,而是行为的封装和覆盖的能力。
function Piece() { }
Piece.prototype.color = "white";
Piece.prototype.getColor = function() { return this.color }
Piece.prototype.move = function() { throw "pure function" };
function Pawn() { }
Pawn.prototype = new Piece();
Pawn.prototype.move = function() { alert("moved"); }
现在:
var p = new Pawn(); p.color = "black";
> p instanceof Piece
真正
p instanceof Pawn
真正
p.getColor()
“黑色”
p.move()
警报...
这是基本的方法,并且有许多库将这变成了对于想要课程的人来说熟悉的东西 - 所以说。
例如,使用JayData,您可以以更加封装的方式编写前一个(在链上自动构造函数调用的奖励:
var Piece = $data.Base.extend("Piece", {
move: function() { throw "pure class" }
});
var Pawn = Piece.extend("Pawn", {
move: function() { ... }
});
var p = new Pawn();
许多关于各种传统OO语言(包括Java,C#和C ++)的好书都特别建议不要在可能的情况下使用“实现继承”。 示例:Joshua Bloch的有效Java。
奇怪的事实是,虽然实现继承似乎给你的代码定期“形状”,但它并没有真正帮助你解决问题; 更常见的是,从长远来看,它会导致问题。
那些作者倾向于给予他们的祝福而不是“接口继承” - 但是在诸如JavaScript之类的鸭子类型语言中,没有必要明确地声明这样的继承。
在JS中,您可以通过简单地将其作为多个对象的属性来“重用”相同的函数。 无论你需要什么样的遗产,你都可以从无到有。
JavaScript甚至没有真正的OOP风格的类,你只能模拟类似的东西。
在您的示例中,您可以通过执行继承
var Pawn = function(teamColor, pos) {
Piece.call(this, teamColor, pos);
}
但是,您通常应该将方法附加到函数原型而不是任何新创建的对象。 在这种情况下,您可以通过设置原型链来模拟继承,例如,像CoffeeScript那样:
var a, b, _ref,
__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; };
a = (function() {
function a() {}
return a;
})();
b = (function(_super) {
__extends(b, _super);
function b() {
_ref = b.__super__.constructor.apply(this, arguments);
return _ref;
}
return b;
})(a);
以下代码块将“扩展”另一个JavaScript原型,并确保“instanceof”运算符对基类和派生类正常工作。
据我所知,将TestB的原型设置为新的TestA允许“instanceof”运算符的逻辑包含。
将此传递给TestA会为新实例提供所有需要的属性和方法。
这样做是风格欲望和实用欲望之间的平衡。 这将适用于大多数浏览器,甚至Internet Explorer,如果你被迫支持它。 它也有帮助,因为同一块中包含的方法“感觉”很像传统的OO语法。
此外,JavaScript不支持传统的面向对象风格的主要原因是它的创始理念。 创始哲学是自由。 这种自由旨在允许开发人员设计自己的样式以满足项目的需求。
function TestA(){
var me = this;
me.method = function(){
}
}
function TestB(){
TestA.call(this);
var me = this;
me.otherMethod = function(){
}
}
TestB.prototype = new TestA();
var test = new TestB();
console.log(test);
console.log(test instanceof TestB);
console.log(test instanceof TestA);
//TestA { method: [Function], otherMethod: [Function] }
//true
//true
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.