टाइपप्रति में mixins

वोट
6

मैं टाइपप्रति के साथ चारों ओर खेल रहा हूँ, और मैं एक जोड़े को मिल गया है कार्यात्मक mixins , Eventableऔर Settable, कि मैं एक के लिए Mixin करना चाहते हैं Model(नाटक यह एक Backbone.js मॉडल की तरह कुछ है) वर्ग:

function asSettable() {
  this.get = function(key: string) {
    return this[key];
  };
  this.set = function(key: string, value) {
    this[key] = value;
    return this;
  };
}

function asEventable() {
  this.on = function(name: string, callback) {
    this._events = this._events || {};
    this._events[name] = callback;
  };
  this.trigger = function(name: string) {
    this._events[name].call(this);
  }
}

class Model {
  constructor (properties = {}) {
  };
}

asSettable.call(Model.prototype);
asEventable.call(Model.prototype);

कोड ऊपर ठीक काम करता है, लेकिन संकलन नहीं होगा अगर मैं की तरह मिश्रित में एक विधि का उपयोग करने की कोशिश की (new Model()).set('foo', 'bar')

मैं इस के चारों ओर से काम कर सकते हैं

  1. जोड़ने interfacemixins के लिए घोषणाओं
  2. घोषित डमी get/ set/ on/ triggerमें तरीकों Modelघोषणा

वहाँ डमी घोषणाओं के चारों ओर एक स्वच्छ रास्ता नहीं है?

04/10/2012 को 04:20
का स्रोत उपयोगकर्ता
अन्य भाषाओं में...                            


3 जवाब

वोट
12

यहाँ एक तरह से उपयोग करते हुए mixins दृष्टिकोण है interfacesऔर एक static create()विधि। इंटरफेस एकाधिक वंशानुक्रम समर्थन ताकि फिर से परिभाषित करने के लिए करने से रोकता है interfacesअपने mixins के लिए और static create()विधि तुम वापस का एक उदाहरण दे रही है का ख्याल रखता है Model()एक के रूप में IModel( <any>डाली एक संकलक चेतावनी को दबाने के लिए की जरूरत है।) आप सभी को नकल करने की आवश्यकता होगी के लिए अपने सदस्य परिभाषाओं Modelपर IModelजो बेकार है, लेकिन इसे प्राप्त करने के लिए आप क्या टाइपप्रति के वर्तमान संस्करण में चाहते स्पष्ट तरीका की तरह लगता है।

संपादित करें: मैं समर्थन mixins के लिए एक से थोड़ा सरल तरीका की पहचान की है और यहां तक कि उन्हें परिभाषित करने के लिए एक सहायक वर्ग बनाया है। विवरण पाया जा सकता है यहाँ पर

function asSettable() {
  this.get = function(key: string) {
    return this[key];
  };
  this.set = function(key: string, value) {
    this[key] = value;
    return this;
  };
}

function asEventable() {
  this.on = function(name: string, callback) {
    this._events = this._events || {};
    this._events[name] = callback;
  };
  this.trigger = function(name: string) {
    this._events[name].call(this);
  }
}

class Model {
  constructor (properties = {}) {
  };

  static create(): IModel {
      return <any>new Model();
  }
}

asSettable.call(Model.prototype);
asEventable.call(Model.prototype);

interface ISettable {
    get(key: string);
    set(key: string, value);
}

interface IEvents {
    on(name: string, callback);
    trigger(name: string);
}

interface IModel extends ISettable, IEvents {
}


var x = Model.create();
x.set('foo', 'bar');
04/10/2012 को 06:46
का स्रोत उपयोगकर्ता

वोट
3

स्पष्ट तरीका यह करने के लिए, हालांकि यह अभी भी, डबल प्रकार घोषणाओं की आवश्यकता है एक मॉड्यूल के रूप mixin परिभाषित करने के लिए है:

module Mixin {
    export function on(test) {
        alert(test);
    }
};

class TestMixin implements Mixin {
    on: (test) => void;
};


var mixed = _.extend(new TestMixin(), Mixin); // Or manually copy properties
mixed.on("hi");

इंटरफेस का उपयोग कर के लिए एक वैकल्पिक वर्गों के साथ यह हैक करना (हालांकि बहु-विरासत की वजह से, आप mixins के लिए एक आम इंटरफ़ेस बनाने की आवश्यकता होगी) है:

var _:any;
var __mixes_in = _.extend; // Lookup underscore.js' extend-metod. Simply copies properties from a to b

class asSettable {
    getx(key:string) { // renamed because of token-clash in asEventAndSettable
        return this[key];
    }
    setx(key:string, value) {
        this[key] = value;
        return this;
    }
}

class asEventable {
    _events: any;
    on(name:string, callback) {
        this._events = this._events || {};
        this._events[name] = callback;
    }
    trigger(name:string) {
        this._events[name].call(this);
  }
}

class asEventAndSettable {
   // Substitute these for real type definitions
   on:any;
   trigger:any;
   getx: any;
   setx: any;
}

class Model extends asEventAndSettable {
    /// ...
}

var m = __mixes_in(new Model(), asEventable, asSettable);

// m now has all methods mixed in.

जैसा कि मैंने स्टीवन के उत्तर पर टिप्पणी की, mixins वास्तव में एक टाइपप्रति सुविधा होना चाहिए।

04/10/2012 को 07:04
का स्रोत उपयोगकर्ता

वोट
1

एक समाधान कीवर्ड को 'नए' अलावा टाइपप्रति वर्ग प्रणाली, लेकिन सिर्फ प्रकार और इंटरफेस की systeme, का उपयोग नहीं करने के लिए है।

    //the function that create class
function Class(construct : Function, proto : Object, ...mixins : Function[]) : Function {
        //...
        return function(){};
}

module Test { 

     //the type of A
    export interface IA {
        a(str1 : string) : void;
    }

    //the class A 
    //<new () => IA>  === cast to an anonyme function constructor that create an object of type IA, 
    // the signature of the constructor is placed here, but refactoring should not work
    //Class(<IA> { === cast an anonyme object with the signature of IA (for refactoring, but the rename IDE method not work )
    export var A = <new () => IA> Class(

        //the constructor with the same signature that the cast just above
        function() { } ,

        <IA> {
            //!! the IDE does not check that the object implement all members of the interface, but create an error if an membre is not in the interface
            a : function(str : string){}
        }
    );


    //the type of B
    export interface IB {
        b() : void;
    }
    //the implementation of IB
    export class B implements IB { 
        b() { }
    }

    //the type of C
    export interface IC extends IA, IB{
        c() : void;
        mystring: string;
    }

     //the implementation of IC
    export var C = <new (mystring : string) => IC> Class(

        //public key word not work
        function(mystring : string) { 

            //problem with 'this', doesn't reference an object of type IC, why??
            //but google compiler replace self by this !!
            var self = (<IC> this);
            self.mystring = mystring;
        } ,

        <IC> {

            c : function (){},

            //override a , and call the inherited method
            a: function (str: string) {

                (<IA> A.prototype).a.call(null, 5);//problem with call and apply, signature of call and apply are static, but should be dynamic

                //so, the 'Class' function must create an method for that
                (<IA> this.$super(A)).a('');
            }

        },
        //mixins
        A, B
    );

}

var c = new Test.C('');
c.a('');
c.b();
c.c();
c.d();//ok error !
23/01/2013 को 00:34
का स्रोत उपयोगकर्ता

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more