Private members in CoffeeScript?

Does anyone know how to make private, non-static members in CoffeeScript? I am currently doing this, which simply uses a public variable starting with an underscore to clarify that it should not be used outside the class:

class Thing extends EventEmitter constructor: (@_name) -> getName: -> @_name 

Putting a variable in a class makes it a static member, but how can I make it non-static? Is this even possible without "fantasy"?

+85
oop private-members coffeescript instance-variables
Jan 13 2018-11-21T00:
source share
11 answers

Is this even possible without "fantasy"?

It is sad to say that you need to be a fantasy.

 class Thing extends EventEmitter constructor: (name) -> @getName = -> name 

Remember: "This is just JavaScript."

+20
Jan 13 2018-11-11T00:
source share

classes are just functions, so they create areas. everything defined inside this scope will not be visible from the outside.

 class Foo # this will be our private method. it is invisible # outside of the current scope foo = -> "foo" # this will be our public method. # note that it is defined with ':' and not '=' # '=' creates a *local* variable # : adds a property to the class prototype bar: -> foo() c = new Foo # this will return "foo" c.bar() # this will crash c.foo 

coffeescript compiles this into the following:

 (function() { var Foo, c; Foo = (function() { var foo; function Foo() {} foo = function() { return "foo"; }; Foo.prototype.bar = function() { return foo(); }; return Foo; })(); c = new Foo; c.bar(); c.foo(); }).call(this); 
+204
Nov 30 '11 at 23:12
source share

I would like to show something even stranger

 class Thing extends EventEmitter constructor: ( nm) -> _name = nm Object.defineProperty @, 'name', get: -> _name set: (val) -> _name = val enumerable: true configurable: true 

Now you can do

 t = new Thing( 'Dropin') # members can be accessed like properties with the protection from getter/setter functions! t.name = 'Dragout' console.log t.name # no way to access the private member console.log t._name 
+10
Sep 26
source share

There is one problem with Vitalyโ€™s answer, and you cannot define the variables that you want to be unique for the region, if you made this name this way and then changed it, the value of the name will change for each individual instance of the class, so there is one way to solve this problem.

 # create a function that will pretend to be our class MyClass = -> # this has created a new scope # define our private varibles names = ['joe', 'jerry'] # the names array will be different for every single instance of the class # so that solves our problem # define our REAL class class InnerMyClass # test function getNames: -> return names; # return new instance of our class new InnerMyClass 

Cannot access an array of names from outside unless you use getNames

check this

 test = new MyClass; tempNames = test.getNames() tempNames # is ['joe', 'jerry'] # add a new value tempNames.push 'john' # now get the names again newNames = test.getNames(); # the value of newNames is now ['joe', 'jerry', 'john'] # now to check a new instance has a new clean names array newInstance = new MyClass newInstance.getNames() # === ['joe', 'jerry'] # test should not be affected test.getNames() # === ['joe', 'jerry', 'john'] 

Compiled Javascript

 var MyClass; MyClass = function() { var names; names = ['joe', 'jerry']; MyClass = (function() { MyClass.name = 'MyClass'; function MyClass() {} MyClass.prototype.getNames = function() { return names; }; return MyClass; })(); return new MyClass; }; 
+2
Feb 24 '14 at 3:02
source share

Here is a solution that builds on a couple of other answers here plus https://stackoverflow.com/a/165444/ . It stores private instances (non-static) in a private class (static) array and uses the object identifier to find out which element of this array contains data belonging to each instance.

 # Add IDs to classes. (-> i = 1 Object.defineProperty Object.prototype, "__id", { writable:true } Object.defineProperty Object.prototype, "_id", { get: -> @__id ?= i++ } )() class MyClass # Private attribute storage. __ = [] # Private class (static) variables. _a = null _b = null # Public instance attributes. c: null # Private functions. _getA = -> a # Public methods. getB: -> _b getD: -> __[@._id].d constructor: (a,b,@c,d) -> _a = a _b = b # Private instance attributes. __[@._id] = {d:d} # Test test1 = new MyClass 's', 't', 'u', 'v' console.log 'test1', test1.getB(), test1.c, test1.getD() # test1 tuv test2 = new MyClass 'W', 'X', 'Y', 'Z' console.log 'test2', test2.getB(), test2.c, test2.getD() # test2 XYZ console.log 'test1', test1.getB(), test1.c, test1.getD() # test1 X uv console.log test1.a # undefined console.log test1._a # undefined # Test sub-classes. class AnotherClass extends MyClass test1 = new AnotherClass 's', 't', 'u', 'v' console.log 'test1', test1.getB(), test1.c, test1.getD() # test1 tuv test2 = new AnotherClass 'W', 'X', 'Y', 'Z' console.log 'test2', test2.getB(), test2.c, test2.getD() # test2 XYZ console.log 'test1', test1.getB(), test1.c, test1.getD() # test1 X uv console.log test1.a # undefined console.log test1._a # undefined console.log test1.getA() # fatal error 
+2
Nov 23 '14 at 13:35
source share

Here's how you can declare private, non-static members in Coffeescript
For full help, you can take a look at https://github.com/vhmh2005/jsClass

 class Class # private members # note: '=' is used to define private members # naming convention for private members is _camelCase _privateProperty = 0 _privateMethod = (value) -> _privateProperty = value return # example of _privateProperty set up in class constructor constructor: (privateProperty, @publicProperty) -> _privateProperty = privateProperty 
+1
Jul 17 '14 at 8:47
source share

A โ€œclassโ€ in coffee scenarios leads to a prototype-based result. Therefore, even if you use a private variable, it is shared between instances. You can do it:

 EventEmitter = -> privateName = "" setName: (name) -> privateName = name getName: -> privateName 

.. leads to

 emitter1 = new EventEmitter() emitter1.setName 'Name1' emitter2 = new EventEmitter() emitter2.setName 'Name2' console.log emitter1.getName() # 'Name1' console.log emitter2.getName() # 'Name2' 

But be careful to close private members before public functions, because the coffee script returns public functions as an object. Take a look at compiled Javascript:

 EventEmitter = function() { var privateName = ""; return { setName: function(name) { return privateName = name; }, getName: function() { return privateName; } }; }; 
+1
Aug 6 '15 at 15:42
source share

Since the coffee script comes down to JavaScript, the only way you can have private variables is to close it.

 class Animal foo = 2 # declare it inside the class so all prototypes share it through closure constructor: (value) -> foo = value test: (meters) -> alert foo e = new Animal(5); e.test() # 5 

This compiles using the following JavaScript:

 var Animal, e; Animal = (function() { var foo; // closured by test and the constructor foo = 2; function Animal(value) { foo = value; } Animal.prototype.test = function(meters) { return alert(foo); }; return Animal; })(); e = new Animal(5); e.test(); // 5 

Of course, this has all the same limitations as all other private variables that you can have with closures, for example, recently added methods do not have access to them, because they were not defined in the same area.

0
Jan 13 2018-11-11T00:
source share

You cannot do this easily with CoffeeScript classes because they use the Javascript constructor template to create classes.

However, you can say something like this:

 callMe = (f) -> f() extend = (a, b) -> a[m] = b[m] for m of b; a class superclass constructor: (@extra) -> method: (x) -> alert "hello world! #{x}#{@extra}" subclass = (args...) -> extend (new superclass args...), callMe -> privateVar = 1 getter: -> privateVar setter: (newVal) -> privateVar = newVal method2: (x) -> @method "#{x} foo and " instance = subclass 'bar' instance.setter 123 instance2 = subclass 'baz' instance2.setter 432 instance.method2 "#{instance.getter()} <-> #{instance2.getter()} ! also, " alert "but: #{instance.privateVar} <-> #{instance2.privateVar}" 

But you lose the grandeur of CoffeeScript classes because you cannot inherit from a class created this way in any other way than using the expand () function. instanceof will stop working, and created objects in this way consume a bit more memory. In addition, you should no longer use the new and super keywords.

The fact is that closures must be created every time an instance of the class is created. Closing elements in pure CoffeeScript classes is created only once - that is, when a class runtime class is created.

0
Jun 02 2018-12-12T00:
source share

Here is the best article I've found about setting up public static members , private static members , public and private members and some other related stuff. It covers a lot of details and comparing js vs. coffee . And for historical reasons, here is the best example code from it:

 # CoffeeScript class Square # private static variable counter = 0 # private static method countInstance = -> counter++; return # public static method @instanceCount = -> counter constructor: (side) -> countInstance() # side is already a private variable, # we define a private variable `self` to avoid evil `this` self = this # private method logChange = -> console.log "Side is set to #{side}" # public methods self.setSide = (v) -> side = v logChange() self.area = -> side * side s1 = new Square(2) console.log s1.area() # output 4 s2 = new Square(3) console.log s2.area() # output 9 s2.setSide 4 # output Side is set to 4 console.log s2.area() # output 16 console.log Square.instanceCount() # output 2 
0
Jun 01 '15 at
source share

If you want to post only individual private messages, just wrap them in the $ variable

 $: requirements: {} body: null definitions: null 

and use @$.requirements

-3
Feb 19 '13 at 16:11
source share



All Articles