JavaScript:使用子类更改默认函数?

时间:2018-05-16 23:44:03

标签: javascript inheritance subclass

我试图使用JavaScript制作简单的游戏。我希望游戏中的每个关卡都有不同的行为。但是,我也想要一些默认行为,因为不会改变游戏的每个部分。

我认为我应该尝试使用子类和继承,也许使用这样的级别基础:



"use strict";

function LevelBase() {
	this.load = function(level) {
		if (level === 1) {
			new Level1(this); // Can't do this = new Level1(this);
		}
	};
	this.func = function() {
		return 123;
	};
}

function Level1(game) {
	this.prototype = game;
	this.func = function() {
		return 456;
	};
}

var game = new LevelBase();
game.load(1);
console.log(game.func()); // Should print 456




然而,这不起作用。它仍然使用默认行为,我感觉这是一个糟糕的方法,会使一切都过于复杂。有没有一种工作方法可以做这样的事情?

任何帮助都将受到高度赞赏!

3 个答案:

答案 0 :(得分:1)

您可以使用game.func = ...直接重载。

"use strict";

function LevelBase() {
	this.load = function(level) {
		if (level === 1) {
			new Level1(this);
		}
	};
	this.func = function() {
		return 123;
	};
}

function Level1(game) {
	game.func = function() {
		return 456;
	};
}

var game = new LevelBase();
game.load(1);
console.log(game.func()); // Should print 456

答案 1 :(得分:1)

If you don't have to support IE 11或者愿意转换,class是一种以与基于类的语言类似的方式实现继承的便捷方式:

class LevelBase {
  load() {
    // ...
  }

  func() {
    return 123;
  }
}

class Level1 extends LevelBase {
  func() {
    return 456;
  }
}

const level = new Level1();
console.log(level.func()); // Prints 456

IMO,这是最简洁的继承方式,它应该表现良好,因为它转换为JavaScript自然的基于原型的继承。

答案 2 :(得分:1)

这是一种适用于IE11或任何其他ES5环境的方法。

它依赖于几个实用程序函数来定义您的类,它支持单继承和重载。您可以将函数保存在先加载的较小脚本中,也可以将其保存在文件的顶部。

主要通知我的方法是,我喜欢使用任何解决方案来获得干净的代码,而这正是我在“适当的”之前提出的。 JS中的类。



/*
	This function attaches a prototype object
	to a constructor function and returns it
	
	It also adds a super & base properties
	which can be used to infer which class an object came from (It's constructor function)
	
	e.g. var obj = new Class();
	
	Or using base on a class to check what it inherits from.
	
	Class.base = Base or Null if it has none
	
	obj.super = class;
*/
function _class(c,p) {
	p.base = null;
	p.super = c;
	c.prototype = p;
	
	return c;
}

/*
	This function takes a base class, constructor function and prototype object
	
	First the properties of the base prototype are iterated through,
	and any that aren't already on our new prototype are copied
	
	This essentially allows us to overload behaviour on the prototype by
	redefining it in decendants.
	
	Next a new constructor function is created that calls the base constructor first
	and then the derrived constructor afterward.
	
	function.apply() is a javascript function that can be applied to function objects
	in essense it's saying "Call this function as if you were a member of the first argument
	(the 'this' variable which would be the new object when the constructor is used) and
	use the same arguments that this outer function was called with".
	
	Another way to explain this is
	
	var obj = new nc(10);
		-> calls into nc with one argument '10'.
			-> That then calls into the base constructor with the same argument and 'this' set to the new object
			-> That then calls into the derrived constructor with the same argument and 'this' set to the new object
*/
_class.extends = function(b,c,p) {
	for (var pr in b.prototype) {
		if (!p[pr]) {
			p[pr] = b.prototype[pr];
		}
	}
	
	function nc() {
		b.apply(this,arguments);
		c.apply(this,arguments);
	}
	
	p.base = b;
	p.super = nc;
	nc.prototype = p;
	
	return nc;
}


var BaseClass = _class(
	// Base Constructor
	function(v1,v2) {
		this.v1 = v1;
		this.v2 = v2;
	},
	
	// Base prototype (Use for constants or class functions)
	{
		printValues: function() {
			console.log(
				this.v1,
				this.v2
			);
		}
	}
);

var DerrivedClass1 = _class.extends(BaseClass,
	function(v1,v2) {
		
	},
	
	{
		// It isn't defined here but this prototype contains the functions from the parent
	}
);

var DerrivedClass2 = _class.extends(BaseClass,
	function(v1,v2) {
		
	},
	
	{
		// This overloads inherited behaviour
		printValues: function() {
			console.log(
				"V1: " + this.v1,
				"V2: " + this.v2
			);
		}
	}
);

var obj_1 = new DerrivedClass1(10,20);
var obj_2 = new DerrivedClass2(30,40);

// This uses inherited behaviour
obj_1.printValues();

// This uses overloaded behaviour
obj_2.printValues();