Frage

Hat jemand wissen, wie private, nicht-statische Member in Coffeescript machen? Zur Zeit mache ich das, was nur eine öffentliche Variable verwendet, um mit einem Unterstrich beginnen zu klären, dass sie nicht verwendet außerhalb der Klasse sein sollten:

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

  getName: -> @_name

Setzen Sie die Variable in der Klasse ist es ein statisches Element, aber wie kann ich es nicht statisch? Ist es überhaupt möglich, ohne „fancy“ zu bekommen?

War es hilfreich?

Lösung

Ist es überhaupt möglich, ohne sie "fancy"?

Traurig zu sagen, dann würden Sie sein müssen Phantasie .

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

Denken Sie daran, "Es ist einfach JavaScript."

Andere Tipps

Klassen sind nur Funktionen, so dass sie Bereiche erstellen. alles in diesem Bereich definiert wird von außen nicht sichtbar sein.

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 kompiliert diese in die folgenden:

(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);

Ich möchte etwas zeigen, auch ausgefallenere

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

Jetzt können Sie tun

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

Es gibt ein Problem mit Vitaly Antwort und das ist nicht Variablen definieren können, dass Sie sein wollen einzigartig auf den Umfang, wenn Sie einen eigenen Namen gemacht auf diese Weise und dann geändert, der Name Wert wäre für jede einzelne Instanz der Klasse ändern, so dass es eine Art, wie wir dieses Problem lösen können

# 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

Es ist nicht unmöglich, die die Namen Array von außen zugreifen, es sei denn Sie verwenden getNames

Test this out

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']

Zusammengestellt 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;
};

Hier ist eine Lösung, die hier auf einige der anderen Antworten zieht und https://stackoverflow.com/a/7579956/1484513 . Es speichert die private Instanz (nicht statisch) Variablen in einem eigenen Klasse (statisch) Array und verwendet eine Objekt-ID zu wissen, welches Element des Arrays für jede Instanz gehören, die Daten enthält.

# 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 t u v

test2 = new MyClass 'W', 'X', 'Y', 'Z'
console.log 'test2', test2.getB(), test2.c, test2.getD()  # test2 X Y Z

console.log 'test1', test1.getB(), test1.c, test1.getD()  # test1 X u v

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 t u v

test2 = new AnotherClass 'W', 'X', 'Y', 'Z'
console.log 'test2', test2.getB(), test2.c, test2.getD()  # test2 X Y Z

console.log 'test1', test1.getB(), test1.c, test1.getD()  # test1 X u v

console.log test1.a         # undefined
console.log test1._a        # undefined
console.log test1.getA()    # fatal error

Hier die beste Artikel, den ich über die Einstellung public static members, private static members, public and private members gefunden, und einige andere ähnliche Sachen. Es umfasst viele Informationen und js vs. coffee Vergleich. Und für die historischen Gründe hier ist das beste Codebeispiel von ihm:

# 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

Hier ist, wie Sie den privaten, nicht-statische Member in Coffeescript
erklären können Für vollständige Referenz können Sie einen Blick auf 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

„Klasse“ in Kaffee-Skripten führt zu einem Prototyp basiert Ergebnis. Also selbst wenn Sie eine private Variable wird zwischen Instanzen gemeinsam genutzt. Sie können dies tun:

EventEmitter = ->
  privateName = ""

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

.. führt zu

emitter1 = new EventEmitter()
emitter1.setName 'Name1'

emitter2 = new EventEmitter()
emitter2.setName 'Name2'

console.log emitter1.getName() # 'Name1'
console.log emitter2.getName() # 'Name2'

Aber seien Sie vorsichtig die privaten Mitglieder vor den öffentlichen Funktionen zu setzen, weil Kaffee Skript die öffentlichen Funktionen als Objekt zurückgibt. Schauen Sie sich die kompilierten Javascript:

EventEmitter = function() {
  var privateName = "";

  return {
    setName: function(name) {
      return privateName = name;
    },
    getName: function() {
      return privateName;
    }
  };
};

Da Kaffee-Skript JavaScript kompiliert unten die einzige Möglichkeit, private Variablen ist durch Verschlüsse haben.

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

Dies wird durch das folgende JavaScript kompiliert nach unten:

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

Natürlich hat dies alle die gleichen Einschränkungen wie alle anderen privaten Variablen, die Sie durch die Verwendung von Verschlüssen kann zum Beispiel neu hinzugefügte Methoden Zugriff auf diese nicht haben, da sie nicht im gleichen Umfang definiert wurden.

Sie können es nicht leicht mit Coffeescript Klassen, weil sie die Javascript-Konstruktor Muster für die Erstellung von Klassen verwenden.

Allerdings könnte man sagen, so etwas wie folgt aus:

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}"

Aber Sie verlieren die Größe der Klassen Coffeescript, weil man nicht erben kann von einer Klasse, die Art und Weise durch irgendeine andere Weise geschaffen als durch verlängern mit () erneut. instanceof wird aufhören zu arbeiten, und objecs erstellt auf diese Weise verbrauchen ein wenig mehr Speicher Bit. Außerdem müssen Sie nicht verwenden Sie die neue und Super Keywords mehr.

Der Punkt ist, dass die Verschlüsse jedes Mal eine Klasse instanziiert erstellt werden müssen. Die Mitgliedsschließungen in reinen Coffeescript-Klassen werden nur einmal erstellt -. Das heißt, wenn die Klasse Laufzeit „type“ aufgebaut ist,

Wenn Sie nur separaten privaten memebers von öffentlichem wollen, nur wickeln Sie es in $ variable

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

und Verwendung @$.requirements

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top