Javascript JS函数和抽象类及原型
以下是我的代码的简化版本:Javascript JS函数和抽象类及原型,javascript,prototype,Javascript,Prototype,以下是我的代码的简化版本: function TextBox () { this.builddom = function () { // Building the text dom } } function ImageBox () { this.builddom = function () { // Building the image dom } } function Box (type) { var hand
function TextBox () {
this.builddom = function () {
// Building the text dom
}
}
function ImageBox () {
this.builddom = function () {
// Building the image dom
}
}
function Box (type) {
var handler =
(type == 'text') TextBox :
(type == 'Image') ImageBox : null;
if (handler) (handler).call (this);
this.builddom = function () {
// Here I would like to call the correct builddom function for the type.
}
}
var textbox = new Box ('text');
textbox.builddom ();
如果Box.builddom不存在,则可以正常工作,并调用与特定类型关联的builddom函数。但我需要在Box中做一些常规的事情,然后调用特定的builddom。如果我给Box builddom起了一个不同的名字,比如Box.dobuilddom,也可以,但是会破坏对Box的一般访问
我认为一些巧妙的原型操作可以完成这项工作,但我找不到它。也许最好避免原型制作,而使用合成:
函数文本框(box){
this.builddom=function(){
console.log('构建文本dom',box.props);
}
}
功能图像框(框){
this.builddom=function(){
console.log('buildingtheimagedom',box.props);
}
}
功能盒(道具){
this.props=props;
this.builddom=function(){
抛出新错误(“不支持的函数”);
}
}
var textbox=new textbox(新框({size:5}));
builddom()代码>如果您想使用原型,您可以这样:
功能文本框(道具){
this.props=props;
}
TextBox.prototype={
builddom:function(){
//构建文本dom
log(“TextBox”,this.props);
}
}
功能图像盒(道具){
this.props=props;
}
ImageBox.prototype={
builddom:function(){
//构建文本dom
log(“ImageBox”,this.props);
}
}
功能盒(类型、道具){
变量处理程序=(类型='text')?文本框:
(type=='Image')?ImageBox:null;
if(处理程序){
调用(这个,道具);
assign(这个,handler.prototype);
}
}
var textbox=新框('text',{text:'some'});
textbox.builddom();
var-imagebox=newbox('Image',{x:1,y:2});
imagebox.builddom()代码>我真的不理解这个概念。这个盒子只是某种容器。它不做任何事情,而是创建一个新实例。这里您真正需要的是一个Box接口,但是js没有接口。如果您想
function TextBox () {
this.builddom = function () {
// Building the text dom
}
}
function ImageBox () {
this.builddom = function () {
// Building the image dom
}
}
var container = {
createBox: function (type){
if (type == "text")
return new TextBox();
else if (type == "image")
return new ImageBox();
else
throw new Error();
}
};
var textbox = container.createBox('text');
textbox.builddom();
如果你想包装对象,另一个选择是使用代理,但我不认为这是你的目标
若以后需要进行类型检查,那个么可以使用继承,但并没有多重继承,所以即使这样也不能模拟接口。顺便说一句,是这样的
function Box (){}
function TextBox () {}
TextBox.prototype = Object.create(Box.prototype, {
constructor:TextBox,
builddom: function () {
// Building the text dom
}
});
function ImageBox () {}
ImageBox.prototype = Object.create(Box.prototype, {
constructor:ImageBox,
builddom: function () {
// Building the image dom
}
});
var container = {
createBox: function (type){
if (type == "text")
return new TextBox();
else if (type == "image")
return new ImageBox();
else
throw new Error();
}
};
var textbox = container.createBox('text');
console.log(
textbox instanceof Box,
textbox instanceof ImageBox,
textbox instanceof TextBox
);
textbox.builddom();
如果不打算使用box类,则无需创建它,而是创建一个工厂函数并返回相应类的新实例
函数AbstractBox(){}
AbstractBox.prototype.builddom=函数(){
console.warn(“未实现的方法”);
};
函数TextBox(){}
TextBox.prototype.builddom=函数(){
log(“调用TextBox.builddom”);
};
函数ImageBox(){}
ImageBox.prototype.builddom=函数(){
log(“调用ImageBox.builddom”);
};
函数ErrorBox(){}
函数createBox(类型){
var handler=Object.create(({
“文本”:文本框,
“图像”:ImageBox
}[类型]| |错误框)。原型);
handler.constructor.apply(handler,[].slice.call(参数,1));
for(AbstractBox.prototype中的var属性){
var方法=AbstractBox.prototype[属性];
if(typeof方法==“函数”&&&!(处理程序中的属性))处理程序[属性]=方法;
}
返回处理程序;
}
(createBox(“文本”)).builddom();//正文
(createBox(“图像”)).builddom();//形象
(createBox(“错误”)).builddom();//错误
不清楚为什么不在这里使用标准原型继承。它将允许您继承或重写父级的方法。例如,ImageBox
继承父方法,而TextBox
覆盖:
/*定义框*/
功能盒(类型){
this.type=type | |“box”
}
Box.prototype.builddom=函数(){
console.log(this.type,“:build called”)
}
/*定义文本框*/
函数文本框(){
框。调用(此“文本”)
}
TextBox.prototype=Object.create(Box.prototype);
/*覆盖方法*/
TextBox.prototype.builddom=函数(){
//也调用父方法?
//Box.prototype.builddom.call(this)
console.log(this.type,“文本框覆盖方法”)
}
/*定义图像框*/
函数ImageBox(){
框。调用(此“图像”)
}
ImageBox.prototype=Object.create(Box.prototype);
var-box=newbox();
builddom();
var textbox=新的textbox();
builddom();
var imageBox=新的imageBox();
builddom()代码>我的建议是使用组合/委派而不是继承(has-a而不是is-a)
为什么不从其他两个函数扩展Box
?这是一个非常奇怪的结构。您似乎希望创建新框
返回从文本框
或图像框
继承的实例,这些实例基于框
的参数。这是可能的,但坦率地说不是个好主意。@T.J.Crowder我完全同意。从任何抽象的角度来看,它都没有意义。在OOP中,您将使用委派ant实际直接传递处理程序
,而不是传递类型
,并试图在此基础上找出要使用的处理程序
。或者,你会有一个某种工厂,返回不同的盒子。没有什么理由像现在这样使用Box()。我要澄清一下。实际上,文本框和图像框不应该是我写的。Box函数是工具箱的一部分,其他开发人员应使用该约束创建xxxbox,以公开builddom方法(以及其他许多方法)。该工具包提供了某种盒子注册,以便能够使用这种新型盒子。这是在Java中使用“接口”或“抽象类”的完美例子。我最好使用JS'class'功能,但它还不能在所有浏览器中使用。很抱歉打断了评论,我没有意识到按Enter键会立即发送它。所以我所有的代码都只引用Box函数。ot
function TextBox () {
this.builddom = function () {
// Building the text dom
}
}
function ImageBox () {
this.builddom = function () {
// Building the image dom
}
}
function Box (type) {
var constructor =
(type == 'text') ? TextBox :
(type == 'Image') ? ImageBox : null;
var delegate = new constructor();
this.builddom = function () {
// Pre-work goes here.
delegate.builddom();
// Post-work goes here.
}
}
var textbox = new Box ('text');
textbox.builddom ();