1

I have two classes, one depends on another. It is implemented like this:

class myns.ClassA
  constructor(@serviceB): ->

  publicFunctionA: ->
    privateFunctionB.call this

  privateFunctionB = ->
    @serviceB.someFunction()

then I instantiate it in a glue piece:

myns.classA = new myns.ClassA(myns.serviceB)

and use as:

myns.classA.publicFunctionA()

The problem here is I want to access serviceB from privateFunctionB. Is there more appriopriate way of doing this besides using call ?

Or perhaps my entire approach is tainted too much by my Java backgound? What I need are interdependent code modules, some kind of equivalent to singleton services. I know I could use coffeescript class functions and avoid instantation but how to handle injecting serviceB in a clean way then?

mrembisz
  • 12,722
  • 7
  • 36
  • 32

2 Answers2

2

You can pass the ClassA instance to the private function as a parameter instead of as the this. If you're keeping each class in their own file and then compiling without the --bare option, i'd recommend putting that private function outside the class and use it just as a normal function (it will be private to the file, so no need to worry about leaking things outside):

privateFunctionB = (a) ->
  a.serviceB.someFunction()

class myns.ClassA
  constructor(@serviceB): ->

  publicFunctionA: ->
    privateFunctionB @

You can also put the function inside the class if you dislike it being at the top level of the file (i prefer to have it there as i think it's easier to understand that it's just a simple function).

epidemian
  • 18,817
  • 3
  • 62
  • 71
  • I was thinking about such thing, thanks a bunch. I wondered mostly what is an accepted practice in such cases. May try that. – mrembisz Oct 22 '12 at 08:59
  • @mrembisz, unfortunately, i think there's no consensus about how to do private methods/attributes in JS. One way of dealing with method privacy in a very "proper" way is using [Crockford's "privileged" methods plus private-by-closure variables](http://www.crockford.com/javascript/private.html) (see also [this answer](http://stackoverflow.com/a/55637/581845)). The downside of that approach is that public methods that use private ones (i.e. privileged) need to be declared in the constructor instead of in the prototype, thus repeating them on every instance. (to be continued...) – epidemian Oct 22 '12 at 17:31
  • I've also seen the leading semicolon used to denote privacy on attributes and methods, which is a simple convention and is probably simpler to understand than Crockford's privileged methods. The downside is, of course, that all those underscores pollute the code with not much benefit. In general, i try to minimize the need for private mutable state (attributes) in objects and implement private functions just as separate functions (as in this answer). – epidemian Oct 22 '12 at 17:31
1

Regarding your question about Java idioms:

There is no notion of public and private in CoffeeScript. Your privateFunctionB is just a normal function declared in the closure of the class. It is in general not a great practice to simulate private functions, because such functions have very different semantics (for example if privateFunctionB was a variable outside your class it would get overwritten, whereas no such risk exists for publicFunctionA).

Therefore the best is to write both functions as normal class properties (that is what you call public functions. Then your code simplifies to this:

class myns.ClassA
  constructor(@serviceB): ->

  functionA: ->
    @functionB()

  functionB: ->
    @serviceB.someFunction()

Another thing you could do for singleton-like things that you can do in CS but not in java is to use global variables. This is often not considered best practice, but it depends on your application (e.g. it's a big no no if writing library code, but might be ok in an end-user sort of thing, depending on usage).

Furthermore you could also consider avoiding the whole class thing and just writing it as a plain object, this possibly will be a good idea if there will be no instances and you plan on doing no subclasing etc.

Jakub Hampl
  • 39,863
  • 10
  • 77
  • 106
  • Thanks, I could be biased by my previous experience, true. I just found out about require.js, will also consider this for managing dependencies. – mrembisz Oct 22 '12 at 09:00