JS于,子类调用父类的函数

概要

  JS虽然没有直接有面向对象的特性,但还是能prototype为了模拟面向对象的特性,如继承和多态。而大多数面向对象的语言(例如C++。Java等一下)相比,JS为了实现面向对象还是有点繁琐,抽象。需要对JS的prototype模式有深刻的理解。

  在开发过程中,有时候会遇到这样一个问题:假设在子类中“覆盖”了超类的某个方法,但仍须要在子类方法中调用一次超类方法,这时候应该怎么做?假设是Java,一个简单的superkeyword就可以解决这个问题,但假设是JS呢?

  解决这个问题的最基本方法能够是:在子类中,使用超类类型。通过applykeyword。以当前类实例引用运行一次超类方法。例如以下:

定义类A

// 定义类A
function A(a) {
	this.a = a;
}
// 为类A定义show方法
A.prototype.show = function() {
		alert("A: " + this.a);
	};

定义类B并从A继承

// 定义类B
function B(a, b) {
	// 调用A的构造函数
	A.apply(this, arguments);
	this.b = b;
}
// 链接A的原型
B.prototype = new A();

实例化类B对象并调用show方法

var b = new B(100, 200);
b.show();

  此时。会运行定义在A中的show方法(显示A.a的值)。表示类B已经从类A中继承了show方法

类B覆盖show方法

// 覆盖show方法
B.prototype.show = function() {
		A.prototype.show.apply(this, arguments);
		alert("B: " + this.b);
	};

// 运行覆盖后的方法
b.show();

  在B的prototype中又一次定义show方法,即能够觉得B类覆盖了A类的show方法。

注意 A.prototype.show.apply(this, arguments) 这一句,实际上是利用了JS的原型特性。在B类对象中(以B类对象)运行了一次A类的show方法。

  JS特殊的动态语言特性使得“覆盖”这个语义能够随时发生。甚至能够通过操作prototype来取消”覆盖“语义,这也正是JS的灵活和强大之处。

更进一步

  通过上面的样例,能够发现,JS的”继承“,”覆盖“和”调用超类方法“尽管不难理解,但写起来仍较为繁琐,以下的代码能够简化这个流程。

(以下代码灵感部分来源于ExtJS库,部分參考自prototype库)

namespace

// 定义根命名空间
ALV = {};

// 定义注冊命名空间的方法
ALV.namespace = function(ns) {
		var root = window;
		var parts = ns.split(".");
		for (var i = 0; i < parts.length; i++) {
			var p = parts[i];
			if (!root[p]) {
				root[p] = {};
			}
			root = root[p];
		}
	};

合并对象的apply方法

// 合并对象成员
ALV.apply = function(obja, objb, def) {
		if (def) {
			ALV.apply(obja, def);
		}
		if (obja && objb && typeof objb === 'object') {
			for (var o in objb) {
				obja[o] = objb[o];
			}
		}
	};

定义类的方法

// 原型定义
ALV.define = function(clazz, config) {
		var parts = clazz.split(".");
		var root = window;
		for (var i = 0; i < parts.length - 1; i++) {
			root = root[parts[i]];
		}
		var cn = parts[parts.length - 1];
		if (!root[cn]) {
			root[cn] = function() {};
		}
		clazz = root[cn];
		// 将proto对象的成员赋值给类的原型
		ALV.apply(clazz.prototype, config);
		return clazz;
	};

定义子类并继承超类的方法

// 定义继承的方法
ALV.extend = function(base, child, proto) {
		// 将超类原型赋值给类的原型
		var c = ALV.define(child);
		if (base && typeof base === "function") {
			c.prototype = new base();
		}
		if (proto && typeof proto == "object") {
			ALV.apply(c.prototype, proto);
		}

		// 调用超类方法
		c.prototype.callParent = function(args) {
				var m;
				for (var o in this) {
					if (this[o] === this.callParent.caller) {
						m = o;
					}
				}
				var method = base.prototype[m];
				if (method && typeof method === "function") {
					method.apply(this, args);
				}
			};
	};

  上述代码中。子类的 prototype 链接到了超类对象上。完毕了 prototype 的继承。而 callParent 方法中,通过对当前类调用方法的查找,找到方法名(m变量),再在超类的 prototype 中找到同名方法,利用超类方法的 apply 操作,在子类对象上完毕对超类方法的调用。

測试代码

// 定义命名空间
ALV.namespace("Alvin.test");
// 定义超类
ALV.define("Alvin.test.A", {
		a: 100,
		show: function() {
				alert("A: " + this.a);
			}
	});
// 定义子类
ALV.extend(Alvin.test.A, "Alvin.test.B", {
		a: 100,
		b: 200,
		show: function() {
				this.callParent(arguments);
				alert("B: " + this.b);
			}
	});
// 实例化B类对象
var b = new Alvin.test.B();
b.show();

  从測试代码中能够看到,Alvin.test.B 类继承了 Alvin.test.A 类,且覆盖了当中的 show 方法。在 B 类的 show 方法中,this.callParent(arguments) 调用完毕了对 A 类show方法的调用。

这样 B 类就可以自然地访问超类方法没有在指定到底有什么关注的超类的名称。

版权声明:本文博主原创文章,博客,未经同意不得转载。

时间: 2024-10-23 22:29:33

JS于,子类调用父类的函数的相关文章

c++子类和父类成员函数重名

1子类和父类返回值参数相同,函数名相同,有virtual关键字,则由对象的类型决定调用哪个函数. 2子类和父类只要函数名相同,没有virtual关键字,则子类的对象没有办法调用到父类的同名函数,父类的同名函数被隐藏了,也可以强制调用父类的同名函数class::funtion_name. 3子类和父类参数不同,函数名相同,有virtual关键字,则不存在多态性,子类的对象没有办法调用到父类的同名函数,父类的同名函数被隐藏了,也可以强制调用父类的同名函数class::funtion_name. 4子

Python基础-接口与归一化设计、抽象类、继承顺序、子类调用父类,多态与多态性

一.接口与归一化设计 Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能). 由于python中没有Interface方法,根据Java接口的定义,可以抽象出python中的接口:一个类所具有的方法的特征集合. 可以通过继承来实现接口方法,在python中,继承有两种用途: 继承基类的方法,并且做出自己的改变或者扩展(代码重用) 声明某个子类兼容于某基类,定义一个接口类Inte

python基础之继承实现原理、子类调用父类的方法、封装

继承实现原理 python中的类可以同时继承多个父类,继承的顺序有两种:深度优先和广度优先. 一般来讲,经典类在多继承的情况下会按照深度优先的方式查找,新式类会按照广度优先的方式查找 示例解析: 没有共同头部父类的类型 1 class E: 2 def test(self): 3 print('from E') 4 # pass 5 class F: 6 def test(self): 7 print('from F') 8 # pass 9 10 class C: 11 def test(se

python子类调用父类的方法

python子类调用父类的方法 python和其他面向对象语言类似,每个类可以拥有一个或者多个父类,它们从父类那里继承了属性和方法.如果一个方法在子类的实例中被调用,或者一个属性在子类的实例中被访问,但是该方法或属性在子类中并不存在,那么就会自动的去其父类中进行查找. 继承父类后,就能调用父类方法和访问父类属性,而要完成整个集成过程,子类是需要调用的构造函数的. 子类不显式调用父类的构造方法,而父类构造函数初始化了一些属性,就会出现问题 如果子类和父类都有构造函数,子类其实是重写了父类的构造函数

第52天学习python 子类调用父类方法

#子类中调用父类#初步程序# class Vehicle:#定义交通工具# Country="China"# def __init__(self,name,speed,load):# self.name=name# self.spedd=speed# self.load=load## def run(self):# print("开动了")## class Subway(Vehicle):#定义个地铁# def __init__(self,name,speed,lo

C++子类调用父类构造函数

构造方法用来初始化类的对象,与父类的其它成员不同,它不能被子类继承(子类可以继承父类所有的成员变量和成员方法,但不继承父类的构造方法).因此,在创建子类对象时,为了初始化从父类继承来的数据成员,系统需要调用其父类的构造方法. 如果没有显式的构造函数,编译器会给一个默认的构造函数,并且该默认的构造函数仅仅在没有显式地声明构造函数情况下创建. 构造原则如下: 1. 如果子类没有定义构造方法,则调用父类的无参数的构造方法. 2. 如果子类定义了构造方法,不论是无参数还是带参数,在创建子类的对象的时候,

node源码详解(四) —— js代码如何调用C++的函数

声明:转载请保留声明头部并标明转载.并私信告知作者.原文:http://www.cnblogs.com/papertree/p/5285705.html 上面讲到node调用Script::Compile()和Script::Run()解析执行app.js,并把io操作和callback保存到default_loop_struct,那么app.js里面js代码如何调用C++的函数呢? 在4.2节进行解释,先在4.1节来点知识预热. 4.1 V8运行js代码的基础知识 —— V8的上下文 来看看g

Python_子类调用父类的方法

1.方式一子类调用父类的方法,包含2中形式的调用.一种形式是在类内部通过继承的方式调用父类的方法,另外一种形式是子类实例化后之后通过继承的方式来调用父类的方法.如下图所示:注意一点,在子类内部通过继承的方式调用父类的属性时,必须要带上self位置参数(self只在实例化过程中和在实例调用属性时才能省略(self本来的含义就是指向实例自己)):而实例在通过继承调用父类的属性或方法时,则不用传self参数,因为实例已经实例化了呀!!!该部分的代码块如下:注意一点,在子类内部通过继承的方式调用父类的属

#python#子类调用父类函数的方法

Python中的子类中的__init__()函数会覆盖父类的函数,一些情况往往需要在子类里调用父类函数. 如下例程里,???处是需要调用父类函数的地方,接下来结合例程具体介绍. 1 1 # -*- coding:utf-8 -*- 2 2 class Student: 3 3 def __init__(self,name): 4 4 self.name=name 5 5 def ps(self): 6 6 print('I am %s'%self.name) 7 7 8 8 class Scor