Effective JavaScript Item 38 在子类构造函数中调用父类构造函数

原创 2014年10月13日 17:17:34

本系列作为Effective JavaScript的读书笔记。

 

在一个游戏或者图形模拟的应用中,都会有场景(Scene)这一概念。在一个场景中会包含一个对象集合,这些对象被称为角色(Actor)。而每个角色根据其类型会有一个图像用来表示,同时场景也需要保存一个底层图形展示对象的引用,被称为上下文(Context)


function Scene(context, width, height, images) {
	this.context = context;
	this.width = width;
	this.height = height;
	this.images = images;
	this.actors = [];
}
Scene.prototype.register = function(actor) {
	this.actors.push(actor);
};
Scene.prototype.unregister = function(actor) {
	var i = this.actors.indexOf(actor);
	if (i >= 0) {
		this.actors.splice(i, 1);
	}
};
Scene.prototype.draw = function() {
	this.context.clearRect(0, 0, this.width, this.height);
	for (var a = this.actors, i = 0, n = a.length; i < n; i++) {
		a[i].draw();
	}
};

场景中所有的角色都继承自一个基类,这个基类用来抽象所有角色具有的属性和方法。比如,每个角色对象都会保存它所在场景的引用,和坐标信息:


function Actor(scene, x, y) {
	this.scene = scene;
	this.x = x;
	this.y = y;
	scene.register(this);
}

同样地,在Actor类型的prototype对象上会定义公共的方法:


Actor.prototype.moveTo = function(x, y) {
	this.x = x;
	this.y = y;
	this.scene.draw();
};
Actor.prototype.exit = function() {
	this.scene.unregister(this);
	this.scene.draw();
};
Actor.prototype.draw = function() {
	var image = this.scene.images[this.type];
	this.scene.context.drawImage(image, this.x, this.y);
};
Actor.prototype.width = function() {
	return this.scene.images[this.type].width;
};
Actor.prototype.height = function() {
	return this.scene.images[this.type].height;
};

有了角色基础类,就可以在其之上创建具体类型了。比如当创建一个宇宙飞船(SpaceShip)角色时,可以这样实现:


function SpaceShip(scene, x, y) {
	Actor.call(this, scene, x, y);
	this.points = 0;
}


为了让SpaceShip的实例也能够拥有所有角色应该有的属性,所以在SpaceShip的构造函数体内首先调用了父类(Actor)的构造函数,紧接着会初始化SpaceShip实例自身的属性,比如以上的points

 

为了让SpaceShip类型确确实实地成为Actor类型的子类型,SpaceShip类型的prototype对象也必须要继承自Actor类型的prototype对象。这可以通过ES5提供的Object.create方法完成(ES5的实现方式可以参考Item 33)


SpaceShip.prototype = Object.create(Actor.prototype);

如果SpaceShipprototype对象是通过调用Actor的构造函数来获得的,那么会出现一系列的问题:


SpaceShip.prototype = new Actor();

在调用Actor构造函数的时候,没法传入合理的参数。因为Actor接受场景对象和坐标信息作为参数,而SpaceShip类型的prototype对象的目的是为了容纳SpaceShip类型中一些公用的属性和方法,显然场景和坐标信息会随着SpaceShip实例的不同而不同,将这些信息放在prototype对象上是不合适的。

 

父类型的构造函数只能在子类型的构造函数中被调用,而子类型的prototype对象是继承自父类型的prototype对象。这一点在创建子类型的prototype时需要注意。

 

一旦完成了子类型prototype对象的创建,就可以在其上设置公用的属性和方法了:


SpaceShip.prototype.type = "spaceShip";
SpaceShip.prototype.scorePoint = function() {
	this.points++;
};
SpaceShip.prototype.left = function() {
	this.moveTo(Math.max(this.x - 10, 0), this.y);
};
SpaceShip.prototype.right = function() {
	var maxWidth = this.scene.width - this.width();
	this.moveTo(Math.min(this.x + 10, maxWidth), this.y);
};

此时,Actor类型,SpaceShip类型以及它们的prototype对象之间的关系如下:




总结

  1. 在子类型的构造函数中调用父类型的构造函数,并显式传入this的指向。
  2. 使用Object.create方法创建子类型的prototype对象来避免对父类型构造函数的调用。

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dm_vincent/article/details/40048241

在C++中子类继承和调用父类的构造函数方法

构造方法用来初始化类的对象,与父类的其它成员不同,它不能被子类继承(子类可以继承父类所有的成员变量和成员方法,但不继承父类的构造方法)。因此,在创建子类对象时,为了初始化从父类继承来的数据成员,系统需...
  • hemmingway
  • hemmingway
  • 2012-08-11 08:43:33
  • 66005

关于父类与子类的构造函数调用顺序

关于父类与子类的构造函数调用顺序
  • qq_36846891
  • qq_36846891
  • 2017-04-08 12:04:32
  • 2151

Java构造函数之调用父类构造函数

子类可以通过super关键字来显式地调用父类的构造函数。 当父类没有提供无参数的构造函数时,子类的构造函数中必须显式的调用父类的构造函数; 如果父类提供了无参数的构造函数,此时子类的构造函数就可以...
  • wyongan1128
  • wyongan1128
  • 2016-09-21 09:54:39
  • 4059

何时子类必须显示调用父类带参构造函数

子类显示调用父类带参构造函数
  • yanghongche
  • yanghongche
  • 2017-01-19 17:51:35
  • 2147

c++ 子类调用父类有参构造函数

http://zhaotao110.blog.sohu.com/262229455.html c++ 子类调用父类有参构造函数 一、 问题    ...
  • wangyin159
  • wangyin159
  • 2015-06-22 11:57:04
  • 2151

python子类调用父类的方法

python子类调用父类的方法 2013/10/09 by Crazyant 2 Comments python和其他面向对象语言类似,每个类可以拥有一个或者多个父类,它们从父类那里...
  • u013083918
  • u013083918
  • 2017-07-12 20:15:59
  • 696

Python实现子类调用父类的方法

如下代码:class A: def __init__(self): self.namea="aaa" def funca(self): print "f...
  • chenlei_525
  • chenlei_525
  • 2017-04-21 10:57:10
  • 3660

C++中子类调用父类的有参构造函数

#include using namespace std; class A { public: int a; int b; A() { cout
  • sddyljsx
  • sddyljsx
  • 2013-06-23 19:54:04
  • 16744

子类调用父类默认构造函数

对文件名为Test.java的java代码描述正确的是() class Person { String name = "No name"; public Person(String n...
  • sszgg2006
  • sszgg2006
  • 2016-02-18 09:04:33
  • 1786

Effective JavaScript Item 38 在子类构造函数中调用父类构造函数

本系列作为Effective JavaScript的读书笔记。   在一个游戏或者图形模拟的应用中,都会有场景(Scene)这一概念。在一个场景中会包含一个对象集合,这些对象被称为角色(Actor...
  • dm_vincent
  • dm_vincent
  • 2014-10-13 17:17:34
  • 3800
收藏助手
不良信息举报
您举报文章:Effective JavaScript Item 38 在子类构造函数中调用父类构造函数
举报原因:
原因补充:

(最多只允许输入30个字)