zoukankan      html  css  js  c++  java
  • Javascript面对对象. 第五篇

    继承

    继承是面向对象中一个核心的概念。其他正统面向对象语言都会用两种方式实现继承:

    一个是接口实现,一个是继承

    而ECMAScript只支持继承,不支持接口实现,而实现继承的方式依靠原型链完成。

    //继承,通过原型链实现
    	function Box(){  //被继承的函数叫超类型(父类,基类)
        		this.name="link"
        	}
       	function Dest(){//继承的函数叫子类型(子类,派生类)
        		this.age=25;
        }
        	function Table(){
       		this.level="dfsfsdf";
        }
       	//通过原型链继承,超类型实例化后的对象实例,赋值给予类型的原型属性
        	//new Box()会将Box构造里的信息和原型里的信息都提交给Dest
        	Dest.prototype=new Box();
        	Table.prototype=new Dest();
    		var dest=new Dest();
       	alert(dest.age)
       	alert(dest.name)
       	
       	var table=new Dest();
       	alert(table.age)
       	alert(table.name)
    

     如果要实例化Dest,那么Box实例中的name="link",原型中添加相同的属性name="xiao",如果有Box有就是link,没有就是xiao

    //继承,通过原型链实现
          	function Box(){  //被继承的函数叫超类型(父类,基类)
          		//this.name="link"
          	}
          	Box.prototype.name="xiao";
          	function Dest(){//继承的函数叫子类型(子类,派生类)
          		this.age=25;
          }
          	
        
          	//通过原型链继承,超类型实例化后的对象实例,赋值给予类型的原型属性
          	//new Box()会将Box构造里的信息和原型里的信息都提交给Dest
          	Dest.prototype=new Box();
          		var dest=new Dest();
          	alert(dest.age)
          	alert(dest.name)  //xiao
    

      ps:以上原型链继承还少一环,那就是Object,所有的构造函数都继承自Object。而继承object是自动完成的,并不需要程序员手动继承。

    //经过继承后的实例,他们的从属关系会是什么?
    			alert(table instanceof Object);   //true
    			alert(dest instanceof Table);      //false,dest是Table的超类
    			alert(table instanceof Dest);    //true
    			alert(table instanceof Box);     //true
    

     在javascript里,被继承的函数称为超类型(父类,基类),继承的函数称为子类型(子类,派生类)。继承也有之前的问题比如字面量重写原型会中断关系,使用引用类型的原型,并且子类型还无法给超类型传递参数。  

    为了解决共享和超类型无法传参的问题,我们采用了一种叫借用构造函数的技术,或者成为对象冒充(伪造对象,经典继承)的技术来解决这两种问题。             

    	//使用对象冒充
    		function Box(name,age){
    			this.name=name;
    			this.age=age; 
    			this.family=['哥哥','妹妹','弟弟']  //引用类型,放在构造里就不会共享。
    		}
    		//Box.prototype.family='姐姐';
    		
    		function Dest(name,age){   
    			Box.call(this,name,age)   //对象冒充,对象冒充只能继承构造里的信息
    		}
    		var dest=new Dest('link',111);
    		dest.family.push('姐姐');
    		alert(dest.name);
    		alert(dest.family);
    		
    		var dest2=new Dest('html',111);
    		alert(dest2.family);
    

    借用构造函数虽然解决了刚才两种问题,但是没有原型,复用则无从谈起。所以,我们需要原型链+借用构造函数的模式,这种模式成为组合继承

        function Box(name,age){
    			this.name=name;
    			this.age=age; 
    			this.family=['哥哥','妹妹','弟弟']  //引用类型,放在构造里就不会共享。
    		}
    		Box.prototype.run=function(){
    			return this.name+this.age+"运行中...";
    		}
    		//构造函数里的方法,放在构造里,每次实例化,都会分配一个内存地址,浪费,所以最好放到原型里,保证多次实例化只有一个地址。
    		function Dest(name,age){   
    			Box.call(this,name,age)   //对象冒充,对象冒充只能继承构造里的信息
    		}
    		
    		Dest.prototype=new Box();   //原型链继承
    		
    		var dest=new Dest('link',111);
    		alert(dest.run());
    

     还有一种继承模式叫:原型式继承:这种继承借助原型并基于已有的对象创建对象,同时还不必因此创建自定义类型。

    我们学习过:
    1.原型链继承,2.借用构造函数继承(对象冒充继承)3.组合继承(结合前俩种)

    4.原型式继承

    //4.原型式继承
    		
    		//临时中转函数
    		function obj(o){    //o表示将要传递进入的一个对象			
    			function F(){}   //F构造是一个临时新建的对象,用来存储传递过来的对象
    			F.prototype=o;   //将o对象实例赋值给F构造的原型对象
    			return new F(); //最后返回这个得到传递过来对象的对象实例
    		}
    		
    		//F.prototype=o 其实就是相当于Dest.prototype=new Box();
    		
    		//这个字面量的声明方式,相当于var box=new Box();
    		var box={
    			name:'link',
    			age:23,
    			family:['哥哥','妹妹','弟弟'] 
    		}
    		//box1等于new F();
    		var box1=obj(box);
    		alert(box1.name);
    		alert(box1.family);
    		box.family.push('姐姐');
    		alert(box1.family);
    		
    		
    		var box2=obj(box);
    		alert(box2.family);
    

     5.寄生式继承=原型式+工厂模式

    //临时中转函数
    		function obj(o){
    		   function F(){}
    		   F.prototype=o;
    		   return new F();
    		}
    		//寄生函数
    		function  create(o){
    			var f=obj(o);
    			return f;
    		}
    		var box={
    			name:'link',
    			age:23,
    			family:['哥哥','妹妹','弟弟'] 
    		}
    		
    		var box1=new create(box);
    		alert(box1.name);
    
    //临时中转函数
    		function obj(o){
    		   function F(){}
    		   F.prototype=o;
    		   return new F();
    		}
    		//寄生函数
    		function  create(box,dest){
    			var f=obj(box.prototype);
    			f.constructor=dest;   //指向了Dest,没有是话指向Box
    			dest.prototype=f;
    			
    		}
    		function Box(name,age){
    			this.name=name;
    			this.age=age;
    		}
    		Box.prototype.run=function(){
    			return this.name+this.age+"运行中。。。";
    		}
    		function Dest(name,age){
    			Box.call(this,name,age)
    		}
    		//通过寄生组合继承来实现继承
    		create(Box,Dest);   //这句话用来替代Dest.prototype=new Box();
    		
    		var dest=new Dest('link',23);
    		alert(dest.run());
    		alert(dest.constructor);   
    
  • 相关阅读:
    UVA 562 Dividing coins --01背包的变形
    HDU 2602 Bone Collector --01背包
    Topcoder SRM 618 Div2 --900
    【转】Python 列表排序
    线段树之区间最大连续和问题
    【转】Python中string的strip,lstrip,rstrip用法
    《Python核心编程》部分代码习题实践(持续更新)
    《Python核心编程》部分错误纠正(勘误表)(持续更新)
    UVA 103 Stacking Boxes --LIS
    POJ 1836 Alignment --LIS&LDS
  • 原文地址:https://www.cnblogs.com/linkhtml/p/5684568.html
Copyright © 2011-2022 走看看