سؤال

CoffeeScript is fantastic, the class system is really all javascript ever needed, a few keywords and a lot less proto* and braces everywhere. I've seen people implement mixins in classes, but I'm wondering if there is a path to implementing an analogy to Java interfaces?

If not it might be a good addition.. After all, it would be good to know if my code can successfully walk/quack like a duck at compile time. The following instructions might better help what would be ideal... Right now you can work around it by creating unit tests (which you should do anyway) so its not that big a deal, but still would be nice.

class definitiona
class definitionb

class featurex
class featurey

class childa extends definitiona implements featurex
class childb extends definitionb implements featurex, featurey
هل كانت مفيدة؟

المحلول

Generally, JavaScripters reject Java-isms like interfaces. After all, the usefulness of interfaces is that they check whether objects "quack like a duck" at compile time, and JavaScript isn't a compiled language. CoffeeScript is, but things like enforcing interfaces is far beyond its scope. A stricter compile-to-JS language like Dart might be more up your alley.

On the other hand, if you wanted to do featurex and featurey as mixins, that's something that's fairly common and easy to do in CoffeeScript-land. You might want to take a look at the classes chapter in The Little Book on CoffeeScript, which shows how easy it is to do this: Just define featurex as an object whose methods you add to the prototype of childa.

نصائح أخرى

I know I'm late to the party. I won't argue the merits of why/why not to do this as it's just a tool in your developer's toolbox, but this is how I do it:

class.coffee

# ref - http://arcturo.github.io/library/coffeescript/03_classes.html#extending_classes
# ref - http://coffeescriptandnodejs.blogspot.com/2012/09/interfaces-nested-classes-and.html

#
# @nodoc
#
classKeywords = ['extended', 'included', 'implements', 'constructor']

#
# All framework classes should inherit from Class
#
class Class

    #
    # Utility method for implementing one of more mixin classes.
    #
    # @param objs [Splat] One or more mixin classes this class will *implement*.
    #
    @implements: (objs...) ->
        for obj in objs
            if typeof obj is 'function' and Boolean(obj.name)
                obj = obj.prototype

            for key, value of obj #when key not in moduleKeywords
                # Assign properties to the prototype
                if key not in classKeywords
                    #console.log 'implementing', value.toString(), 'as', key
                    @::[key] = value

            obj.included?.apply(@)
        this

    #
    # Utility method for adding getter/setters on the Class instance
    #
    # @param prop [String] The name of the getter/setter.
    # @param desc [Object] The object with a getter &/or setter methods defined.
    #
    @property: (prop, desc)-> Object.defineProperty @prototype, prop, desc

interface.quack.coffee

class iQuack 
    quack: -> throw new Error 'must implement interface method'

duck.coffee

class Duck extends Class 
    @implements iQuack

    quack: -> console.log 'quack, quack'

https://gist.github.com/jusopi/3387db0dd25cd11d91ae

I have the same problem, and I've tried to solve it by adding method includes to Function. I described it here. This solution allows implementing multiple interfaces and provides additional method for Object prototype that can be used instead of instanceof operator (as we can't override any JavaScript operator).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top