#261 enhancement
Nagib C.Kanaan

Class Create with Interfaces support.

Reported by Nagib C.Kanaan | August 1st, 2008 @ 07:31 PM

I changed the "Class" to make it support Interfaces.

It's just one idea.

thanks

Comments and changes to this ticket

  • Nagib C.Kanaan

    Nagib C.Kanaan August 1st, 2008 @ 07:52 PM

    • Assigned user set to “Christophe Porteneuve”
    var objInterface = new Interface('add','remove');
    var objClass= Class.create().implements(objInterface);
    
    Object.extend(objClass.prototype, {
      add: function() { }
    });
    
    new objClass;
    
    // Correct
    // Object.extend(objClass.prototype, {
    //   add: function() { },
    //   remove: function() { }
    // }); 
    
  • John-David Dalton

    John-David Dalton August 1st, 2008 @ 08:03 PM

    • State changed from “new” to “enhancement”

    Can you create a more targeted patch and provide some unit tests

  • Nagib C.Kanaan

    Nagib C.Kanaan August 1st, 2008 @ 09:12 PM

    I send the file with changes....

    but here the changes.

    /* Class Interface */
    var Interface = function() {
    	var methods = $A(arguments);
        if(arguments.length < 1)
            throw new SyntaxError("Interface constructor called without arguments, but expected min 1.");
       
        this.methods = methods.invoke('toString');
    };    
    
    /* Based on Alex Arnell's inheritance implementation. */
    var Class = {
      create: function() {
        var parent = null, properties = $A(arguments);
        if (Object.isFunction(properties[0]))
          parent = properties.shift();
    
        function klass() {
          this.initialize.apply(this, arguments);
        }
    
        Object.extend(klass, Class.Methods);
        klass.superclass = parent;
        klass.subclasses = [];
    
        if (parent) {
          var subclass = function() { };
          subclass.prototype = parent.prototype;
          klass.prototype = new subclass;
          parent.subclasses.push(klass);
        }
    
        for (var i = 0; i < properties.length; i++)
          klass.addMethods(properties[i]);
    
        if (!klass.prototype.initialize)
          klass.prototype.initialize = Prototype.emptyFunction;
    
    	klass.prototype.ensureImplements = function() {
          if ( !klass.interfaces || klass.interfaces.length < 1 )
            return true;
          for (var i = 0; i < klass.interfaces.length; i++) {
    	    var methods = klass.interfaces[i].methods;
    	    for (var j = 0; j < methods.length; j++) {
              if(!this[methods[j]] || typeof this[methods[j]] !== 'function') {
                throw new SyntaxError("Object does not implement all interfaces. Method '" + methods[j] + "' was not found.");
              }
    	    }
          }
        };
    
    	klass.prototype.initialize = function () {
    		if( this.ensureImplements() ) {
    			return klass.prototype.initialize();
    		}
    	}
    
        klass.prototype.constructor = klass;
    
        return klass;
      }
    };
    
    Class.Methods = {
      addMethods: function(source) {
        var ancestor   = this.superclass && this.superclass.prototype;
        var properties = Object.keys(source);
    
        if (!Object.keys({ toString: true }).length)
          properties.push("toString", "valueOf");
    
        for (var i = 0, length = properties.length; i < length; i++) {
          var property = properties[i], value = source[property];
          if (ancestor && Object.isFunction(value) &&
              value.argumentNames().first() == "$super") {
            var method = value, value = Object.extend((function(m) {
              return function() { return ancestor[m].apply(this, arguments) };
            })(property).wrap(method), {
              valueOf:  function() { return method },
              toString: function() { return method.toString() }
            });
          }
          this.prototype[property] = value;
        }
    
        return this;
      },
      implements: function() {
        var interfaces = $A(arguments);
        if (interfaces.length)
          this.interfaces = interfaces;
        return this;
      }
    };
    
  • Nagib C.Kanaan

    Nagib C.Kanaan August 1st, 2008 @ 09:14 PM

    • sorry for identation. i used "TAB". ¬¬
  • Juriy Zaytsev

    Juriy Zaytsev August 2nd, 2008 @ 12:36 AM

    1) Would be helpful to see the actual changes (rather than unified file) : )

    2)

    if(!this[methods[j]] || typeof this[methods[j]] !== 'function') {
    

    This seems a little redundant and not too reliable (typeof 'function' already ensures truthiness of a property) but returns true for RegExp's and NodeLists in earlier WebKit builds.

    Object.isFunction should be safer in this case:

    if (Object.isFunction(this[methods[j]])) { ... }
    

    3) `implements` seems weird as well. I would change it to:

    ...
    implements: function() {
        if (arguments.length)
          this.interfaces = $A(arguments);
        return this;
      }
    ...
    

    4) Same goes for `Interface`:

    var Interface = function() {
      if (!arguments.length)
        throw SyntaxError("Interface constructor called without arguments, but expected min 1.");
        // faster and shorter than invoke
      this.methods = $A(arguments).map(String);
    };
    
  • Nagib C.Kanaan

    Nagib C.Kanaan August 4th, 2008 @ 03:12 PM

    • Tag changed from class, function, patched to class, function, needs_patch, needs_tests

    Thanks, Juriy Zaytsev.

    I update the js file.

  • Nagib C.Kanaan

    Nagib C.Kanaan August 4th, 2008 @ 03:15 PM

    • Tag changed from class, function, needs_patch, needs_tests to class, function, needs_tests, patched

    I send new file.

  • Nagib C.Kanaan

    Nagib C.Kanaan August 4th, 2008 @ 03:20 PM

    • Assigned user changed from “Christophe Porteneuve” to “Juriy Zaytsev”
  • Nagib C.Kanaan
  • Nagib C.Kanaan

    Nagib C.Kanaan August 4th, 2008 @ 05:06 PM

    The Interfaces idea i got from this booL "Pro JavaScript Design Patterns" (by Ross Harmes and Dustin Diaz).

    I just adapted the idea of the book.

  • Tobie Langel

    Tobie Langel July 24th, 2009 @ 01:55 AM

    • Tag changed from class, function, needs_tests, patched to function, needs_tests, patched, section:lang

    [not-tagged:"class" tagged:"section:lang" bulk edit command]

  • Tobie Langel

    Tobie Langel July 24th, 2009 @ 02:07 AM

    • Tag changed from function, needs_tests, patched, section:lang to needs_tests, patched, section:lang

    [not-tagged:"function" bulk edit command]

  • Tobie Langel

    Tobie Langel July 24th, 2009 @ 02:26 AM

    • Tag changed from needs_tests, patched, section:lang to missing:tests, patched, section:lang

    [not-tagged:"needs_tests" tagged:"missing:tests" bulk edit command]

  • Tobie Langel

    Tobie Langel July 24th, 2009 @ 03:36 AM

    • Tag changed from missing:tests, patched, section:lang to needs:tests, patched, section:lang

    [not-tagged:"missing:tests" tagged:"needs:tests" bulk edit command]

  • T.J. Crowder

    T.J. Crowder November 16th, 2009 @ 04:50 PM

    • Assigned user cleared.

    [responsible:none bulk edit command]

  • Shubham Thakur

    Shubham Thakur January 19th, 2019 @ 01:28 PM

    • Importance changed from “” to “”

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

The Prototype JavaScript library.

Shared Ticket Bins

Pages