美文网首页
面向对象——继承

面向对象——继承

作者: IvyAutumn | 来源:发表于2018-12-15 17:48 被阅读0次

    许多OO语言都支持两种继承方式:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际的方法。ECMAScript只支持实现继承,而且其实现继承主要是依赖原型链来实现的。
    以一个例子来说明一些知识:

    function SuperType(){
        this.property = true;
    }
    SuperType.prototype.getSuperValue = function(){
        return this.property;
    };
    
    function SubType(){
        this.subproperty = false;
    }
    
    //继承 SuperType
    SubType.prototype = new SuperType(); //new了一个SuperType类的实例
    
    SubType.prototype.getSubValue = function(){
        return this.subproperty;
    };
    
    var instance = new SubType();
    alert(instance.getSuperValue());
    

    确定原型和实例的关系

    1.使用instanceof
    只要用这个操作符来测试实例与原型链中出现过的构造函数,结果就会返回true

    alert(instance instanceof Object); //true
    alert(instance instanceof SuperType); //true
    alert(instance instanceof SubType); //true
    

    2.使用isPrototypeOf()
    只要是原型链中出现过的原型,都可以说是该原型链所派生的实例原型。

    alert(Object.prototype.isPrototypeOf(instance)); //true
    alert(SuperType.prototype.isPrototypeOf(instance)); //true
    alert(SubType.prototype.isPrototypeOf(instance)); //true
    

    原型链的问题

    1.包含引用类型值所带来的问题。例如

    function SuperType(){
        this.colors = ["a", "b", "c"];
    }
    
    function SubType(){
    
    }
    
    //继承了SuperType
    SubType.prototype = new SuperType();
    
    var instance1 = new SubType();
    instance1.colors.push("d");
    alert(instance1.colors); //"a,b,c,d"
    
    var instance2 = new SubType();
    alert(instance2.colors); //"a,b,c,d"
    

    结果是SubType的所有实例都会共享同一个colors属性,这不是我们想要的。
    2.在创建子类型的实例时,不能向超类型的构造函数中传递参数。

    以上两个问题都可以使用“借用构造函数”(也称伪造对象或经典继承)来解决

    借用构造函数

    • 使用apply()和call()方法在新创建的对象上执行构造函数。重写上面的例子
    function SuperType(){
        this.colors = ["a", "b", "c"];
    }
    
    function SubType(){
        //继承了SuperType
        SuperType.call(this);
          //SuperType.apply(this);
    }
    
    var instance1 = new SubType();
    instance1.colors.push("d");
    alert(instance1.colors); //"a,b,c,d"
    
    var instance2 = new SubType();
    alert(instance2.colors); //"a,b,c"
    
    • 借用构造函数的问题
      回到了构造函数模式,函数无法实现复用。

    组合继承

    也叫作伪经典继承。使用原型链实现对原型属性和方法的继承,通过借用函数来实现对实例属性的继承。

    function SuperType(name){
        this.name = name;
        this.colors = ["a", "b", "c"];
    }
    SuperType.prototype.sayName = function(){
        alert(this.name);
    };
    
    
    function SubType(name,age){
        //继承属性
        SuperType.call(this,name);
        
        this.age = age;
    }
    
    //继承方法
    SubType.prototype = new SuperType();
    SubType.prototype.constructor = SubType;
    SubType.prototype.sayAge = function(){
        alert(this.age);
    }
    
    var instance1 = new SubType("Nicholas", 29);
    instance1.colors.push("d");
    alert(instance1.colors); //"a,b,c,d"
    instance1.sayName();  //"Nicholas"
    instance2.sayAge();  //29
    
    var instance2 = new SubType("Greg",27);
    alert(instance2.colors); //"a,b,c"
    instance1.sayName();  //"Greg"
    instance2.sayAge();  //27
    

    原型式继承

    ECMAScript5通过新增Object.create()方法规范化了原型式继承。该方法接受两个参数;

    • 用作新对象原型的对象
    • (可选)为新对象定义额外属性的对象
    var person = {
        name: "Nicholas",
        friends: ["Shelby", "Count", "Van"]
    };
    
    var anotherPerson = Object.create(person,{
        name:{
            value: "Greg"
        }
    });
    
    alert(anotherPerson.name);  //"Greg"
    

    注意:使用引用类型值的属性始终都会共享相应的值

    寄生式继承

    寄生式继承的思路与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再返回对象。


    最理想的继承范式——寄生组合式继承

    本质上是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。寄生组合式继承的基本模式如下:

    function inheritPropotype(subType,superType){
        var prototype = object(superType.prototype); //创建对象
        prototype.constructor = subType; //增强对象
        subType.prototype = prototype; //指定对象
    }
    

    该示例函数实现了寄生组合式继承最简单的形式。该函数接受两个参数:子类型构造函数和超类型构造函数。在函数内部:
    1.创建超类型原型的一个副本
    2.为创建的副本添加constructor属性,从而弥补因为重写原型而失去的默认constructor属性
    3.将新创建的对象(即副本)赋值给子类型的原型。

    function SuperType(name){
        this.name = name;
        this.colors = ["a", "b", "c"];
    }
    SuperType.prototype.sayName = function(){
        alert(this.name);
    };
    
    
    function SubType(name,age){
        //继承属性
        SuperType.call(this,name);
        
        this.age = age;
    }
    
    //继承方法
    inheritPrototype(SubType,SuperType);
    SubType.prototype.sayAge = function(){
        alert(this.age);
    }
    

    相关文章

      网友评论

          本文标题:面向对象——继承

          本文链接:https://www.haomeiwen.com/subject/eauwhqtx.html