【问题标题】:JavaScript - Special multiple inheritanceJavaScript - 特殊的多重继承
【发布时间】:2013-09-01 09:27:33
【问题描述】:

假设我有以下对象类型:

var Positionable = function() { };
Positionable.prototype.x = 0;
Positionable.prototype.y = 0;

var Sizable = function() { };
Sizable.prototype.w = 0;
Sizable.prototype.h = 0;

var Fadable = function() { };
Fadable.prototype.a = 0;

我想要一个函数,允许我创建一个子类型,该子类型可以从其他几种类型继承。例如,我可以创建一个类型 Rectangle,它会继承自 PositionnableSizable

我可以链接原型:

var Rectangle = function() { };
Sizable.prototype = new Positionable;
Rectangle.prototype = new Sizable;

但我不喜欢这种方法有两个原因:

  • 它会导致 Sizable 继承自 Positionable,这意味着如果我希望另一个类型是 Sizable 而不是 Positionable,我做不到;

  • 这意味着Sizable 对象也是Positionnable,这在语义上并不好,因为Sizable 对象没有理由成为Positionnable 而不是其他方式。

所以我首先考虑合并原型,假设我有一个函数void merge( type dst, type src, bool overwrite ),在循环中我会简单地将每个基类原型合并到子类型原型中。这不会创建一个链(这就是我想要的,如上所述)

但这会导致另一个问题:由于我没有使用 new,因此不会调用基本构造函数。所以我想知道,有没有办法也合并构造函数?例如,如果我可以访问和引用基本构造函数,我可以将这些基本构造函数中的每一个存储在一个数组中,并为子类型构造函数分配一个连续调用这些构造函数的函数。

我怎么能用构造函数做到这一点?或者也许还有其他方法?

感谢您的帮助!

【问题讨论】:

    标签: javascript oop object inheritance constructor


    【解决方案1】:
    if you use Object.Create(),you have to think about browser compatibility. you can write
    a function to resolve the issue.eg: 
    
         function multipleinheritPrototype() {
            if (arguments.length == 0) {
                return;
            }
            var args = arguments;
            var sub = args[0];
            var constructor = sub.prototype.constructor;
            if (!Object.create) {
                Object.prototype.create = function (obj) {
    
                    function f() {
                    }
    
                    f.prototype = obj;
                    return new f();
                };
            }
            var base;
            for (var i = 1; i < args.length; i++) {
                base = Object.create(args[i].prototype);
                for (var attr in base) {
                    sub.prototype[attr] = base[attr];
                }
            }
            sub.prototype.constructor = constructor;
    
        }      
        you can such so use it.
        multipleinheritPrototype(Rectangle, Sizeable, Positionnable);
    

    【讨论】:

    【解决方案2】:

    由于 JavaScript 不支持多重继承,您必须解析为 mixins。就像您说的,您必须将其中一个原型的方法复制到子原型中。

    构造函数应该在子构造函数内部调用。这是一个例子:

    var Rectangle = function() {
        Sizeable.call(this);
        Positionnable.call(this);
    };
    // Rectangle inherits from Sizeable
    Rectangle.prototype = Object.create(Sizeable.prototype);
    // Mixin Positionnable
    merge(Rectangle.prototype, Positionnable.prototype);
    
    // alternatively you could mixin both of the prototypes
    

    另见:Benefits of using `Object.create` for inheritance


    function mixin(Target) {
        var args = arguments;
    
        // merge prototypes
        for(var i = 1; i < args.length; i++) {
            merge(Target.prototype, args[i].prototype);
        }
    
        // a new constructor function which calls all 
        // the passed constructor functions
        var F = function() {
            var instance = Target.apply(this, arguments);
            for (var i = 1; i < args.length; i++) {
                args[i].call(instance);
            }
            return instance;
        };
        F.prototype = Target.prototype;
        return F;
    };
    
    // usage
    
    Rectangle = mixin(Rectangle, Sizeable, Positionnable);
    

    这在一个假设下有效:mixin 构造函数不期望任何参数。如果必须向它们传递参数,则必须在目标/子构造函数中显式调用它们。

    【讨论】:

    • 感谢您的帮助。如果没有其他方法,我可能不会这样做,但是我看到的“问题”是我必须做两件事而不是一件事:1)在子构造函数中调用父构造函数,2)合并原型.我想在一个函数中完成所有这些,但为了能够做到这一点,我需要有可能访问和分配构造函数。可能吗 ?谢谢。
    • @Virus721:您应该始终在子构造函数中调用父构造函数,因为这是所有特定于实例的初始化发生的地方。当然,如果父构造函数不做任何事情(即它们不包含任何代码),那么您不必调用它们。如果您可以重新定义 Rectangle 函数,您可以自动化整个过程。我将发布一个示例。
    • Dojo 的 mixin 功能在阅读这个问题时浮现在脑海中,并自动处理构造函数链。根据您的需求和要求,我建议您进行调查。
    • 感谢您的回答。我会看看,但我希望我的图书馆不依赖任何东西。 @Felix Kling 那时我可能会去。此外它更灵活,因为我可以选择不使用您的方法调用构造函数。
    • @Virus721:很高兴能帮上忙!如果您需要支持不支持Object.create 的旧版浏览器,请包括:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
    猜你喜欢
    • 2018-06-24
    • 1970-01-01
    • 2011-04-15
    • 1970-01-01
    • 2019-03-16
    • 2013-01-12
    • 2015-04-09
    • 2015-10-14
    相关资源
    最近更新 更多