Question

I have a CoffeeScript code, which is a driver code for neo4j. In that it has a class PropertyContainer which has two function get and set which are listed as language helpers. and below that are self and data , which are basically prototypical properties of this object. these can be accessed like a.self and a.data.

What i don't understand is why their is a get and set before them, in the following code. the get and set clearly identifies here is the property is being read or written to but how is it working. In CoffeeScript you define prototypical properties as, s prop_name: -> somecode but if you put get prop_name: -> somecode shouldn't this change the property name to something that get returned after get prop_name. I am very new to CoffeeScript, so maybe i am missing something. Please Help.

class PropertyContainer

    #
    # Construct a new wrapper around a Neo4j property container with the given
    # data directly from the server at the given Neo4j {GraphDatabase}.
    #
    # @private
    # @param db {GraphDatbase}
    # @param data {Object}
    #
    constructor: (db, data) ->
        @db = db
        @_request = db._request     # convenience alias

        @_data = data or {}
        @_data.self = data?.self or null

    ### Language helpers: ###

    get = (props) =>
        @::__defineGetter__ name, getter for name, getter of props
    set = (props) =>
        @::__defineSetter__ name, setter for name, setter of props

    ### Properties: ###

    #
    # @property {String} The URL of this property container.
    #
    # @todo This might be an implementation detail; should we remove it?
    #   If not, should it at least be renamed to just URL?
    #
    get self: -> @_data.self or null

    #
    # @property {Object} This property container's properties. This is a map
    #   of key-value pairs.
    #
    get data: -> @_data.data or null
    set data: (value) -> @_data.data = value

This is actually a Driver for Neo4j based on REST API. I don't think it has anything to do with the GET method of HTTP. i have checked for __defineGetter__ and __defineSetter__, these are nowhere else to be seen in the whole library, except for when used in a similar way for other Classes. May be these are some CoffeeScript internal Prototype Prototypes. Would love if anyone could shed some light on this. Thanks again.

Was it helpful?

Solution

A CoffeeScript class is a function definition with a bunch of class-ish stuff layered on top. This means that you can put pretty any code you want inside a class. So if we look at this:

class C
    f = -> #...
    f(6)

then we have a private function, f, and a simple function call, f(6).

Now if we add a => in the mix:

class C
    f = => #...

then f becomes bound to the class so that @ inside f will be C itself.

Now we can apply that to the class in question:

class PropertyContainer
    #...

    get = (props) =>
        @::__defineGetter__ name, getter for name, getter of props
    set = (props) =>
        @::__defineSetter__ name, setter for name, setter of props

    get self: -> @_data.self or null

So we have two functions, get and set, that are abound to PropertyContainer so that @ inside get and set is PropertyContainer. Then we have a call to the get function and adding some parentheses and braces to highlight the structure:

get({ self: (-> @_data.self or null ) })

we should start to see what's going on. The get self ... is just a call to the get function with an object parameter, that object has a single key (self) whose value is a function.

That makes the whole get self ... call look like this:

PropertyContainer::__defineGetter__('self', -> @_data.self or null)

Then if we look at what __defineGetter__ does:

// Non-standard and deprecated way
var o = {};
o.__defineGetter__("gimmeFive", function() { return 5; });
console.log(o.gimmeFive); // 5

we see that we're just setting up o.self as an accessor alias for o._data.self so that this:

o = new PropertyContainer(...)
o.self

is really the same as:

o = new PropertyContainer(...)
o._data.self

or more generally, the get function allows you to send a simple property access to a function. You should also note the "standard compliant" examples from the MDN page:

// Using the get operator
var o = { get gimmeFive() {return 5}};
console.log(o.gimmeFive); // 5

Now we see that get inside PropertyContainer is emulating JavaScript's get operator using the non-standard __defineGetter__ function.

The set function inside PropertyContainer similarly emulates JavaScript's set operator.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top