Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CoffeeScript, implementing 'implements'

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
like image 326
Core Avatar asked Nov 29 '11 18:11

Core


3 Answers

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.

like image 130
Trevor Burnham Avatar answered Oct 24 '22 07:10

Trevor Burnham


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

like image 30
jusopi Avatar answered Oct 24 '22 08:10

jusopi


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).

like image 41
Mariya Davydova Avatar answered Oct 24 '22 08:10

Mariya Davydova