简体   繁体   English

CoffeeScript私有类实例变量

[英]CoffeeScript Private Class Instance Variables

I have the following CoffeeScript code: 我有以下CoffeeScript代码:

class Person
  secret = 0
  constructor: (@name, @age, @alive) ->
  inc: -> secret++

Which compiles to the following JavaScript code: 其中编译为以下JavaScript代码:

var Person;
Person = (function() {   
    var secret;
    secret = 0;

    function Person(name, age, alive) {
        this.name = name;
        this.age = age;
        this.alive = alive;
    }
    Person.prototype.inc = function() {
        return secret++;
    };
    return Person;
})();

Currently secret is shared between all instances of Person . 目前在Person所有实例之间共享secret Is there a way to make secret a private instance variable in CoffeeScript? 有没有办法在CoffeeScript中secret私有实例变量?

I figured out a solution. 我想出了一个解决方案。 I am not sure if this is the best solution, so I am still open to others. 我不确定这是否是最好的解决方案,所以我仍然对其他人开放。

CoffeeScript: CoffeeScript的:

class Person
  constructor: (@name, @age, @alive) ->
    secret = 0
    @inc = -> secret++;

JavaScript: JavaScript的:

var Person;
Person = (function() {
    function Person(name, age, alive) {
        var secret;
        this.name = name;
        this.age = age;
        this.alive = alive;
        secret = 0;
        this.inc = function() {
            return secret++;
        };
    }
    return Person;
})();

There is no concept of private members in CoffeeScript as there is none in JavaScript. CoffeeScript中没有私有成员的概念,因为JavaScript中没有。 There are local variables, which you do utilize well in your own solution , but while your solution does hide the secret variable from anything outside of a constructor function, it also introduces an overhead of redeclaring the inc method on every instantiation of a class Person . 有局部变量,你利用好你自己的解决方案 ,但在你的解决方案确实隐藏secret来自外部的任何变量constructor功能外,还引入了重新声明中的开销inc方法在类的每个实例Person

A mistake very common in JavaScript community is trying to project inexistent features of other languages on it, which an attempt of mimicing private members is obviously a case of. JavaScript社区中一个非常常见的错误是试图在其上设计其他语言的不存在的特征,这种模仿私人成员的尝试显然是一个例子。 There's no such concept in it and thinking deeper you'll conclude that it would be just unnatural to an extremely loose dynamic environment which JavaScript is. 其中没有这样的概念,并且思考得更深,你会得出结论,JavaScript是一个非常宽松的动态环境,这将是不自然的。

So don't waste your time and performance of your application on implementing inexistent constructs. 因此,不要浪费你的应用程序的时间和性能来实现不存在的结构。 Just concentrate on solving your problem - not the problems of lacking language features. 只需专注于解决您的问题 - 而不是缺乏语言功能的问题。

Now ask yourself: what is so hurtful in having all members public? 现在问问自己:让所有成员公开会有什么伤害?

Taking everything said into account the ultimate solution would be: 考虑到所有因素,最终的解决方案是:

class Person
  constructor: (@name, @age, @alive) ->
    @secret = 0
  inc: -> @secret++

While it won't truly hide them, the convention is to prefix "private" members with an underscore. 虽然它不会真正隐藏它们,但惯例是在“私人”成员前加上下划线。 The idea here is that folks consuming this should assume that such members are implementation details and are advised not to use them. 这里的想法是,消费这个的人应该假设这些成员是实现细节,并建议不要使用它们。

Here is a trick that will fulfill the requirement most of the time: 这是一个大多数时间都能满足要求的技巧:

msg = "Result-----------\n"

class Dog

  #public variable
  dogName: null

  #private variables
  _private = []

  constructor: (@dogName, surname) ->
    _private[@dogName] = {surname: surname}

  #public method (note the => instead of ->)
  walk: =>
    msg += "#{@dogName} is walking\n"
    sayHello(@dogName, _private[@dogName].surname)

  #private method
  sayHello = (dog, surname) ->
    msg += "Hi! says #{dog}. Call me #{surname}\n"

window.ralph = new Dog("Ralph", "Ralphie")
window.peter = new Dog("Peter", "Pitty")
window.rex = new Dog("Rex", "Roxie")
rex.walk()
peter.walk()
ralph.walk()

alert msg

but you have to keep in mind that : _private grows with each new instance (it is a shared array) and your key (in this case @dogName) has to be unique accross instances. 但是你必须记住:_private随着每个新实例(它是一个共享数组)而增长,而你的密钥(在这种情况下是@dogName)必须在整个实例中是唯一的。

Try it 试试吧

请参阅此主题 ,您只能通过闭合的getter函数使其工作

You are actually hiding implementation details by declaring a member private. 实际上,您通过声明成员私有来隐藏实现细节。 By using the inheritance you can hide implementation details, by declaring an 'abstract' class (which actually doesn't exist in CoffeeScript, as far as I know) and extending it with your own implementation. 通过使用继承,您可以通过声明一个“抽象”类(实际上在CoffeeScript中不存在,据我所知)并使用您自己的实现扩展它来隐藏实现细节。 Like so: 像这样:

  class bottle
        drink: ->
        empty: ->

  class bottle_impl extends bottle
        drink: -> 
             if count > 0
                 alert "drinking for the " + _count + " time."
       empty: -> @_count = 0
       _count: 4

now every function that returns a bottle should actually return a bottle_impl (while hiding that fact from the user in the comments). 现在,每个返回瓶子的函数实际上应该返回一个bottle_impl(同时在注释中将该事实隐藏起来)。 Unfortunatly, when extending a bottle, you won't extend a bottle_impl which is probably not what you want. 不幸的是,当扩展一个瓶子时,你不会扩展一个可能不是你想要的bottle_impl。

hmmmmmmmm not completely true. 嗯,不完全正确。 if you want private members you can't really get private members but if you really really want it you can have it 如果你想要私人会员你不能真正得到私人会员,但如果你真的想要它,你可以拥有它

class person 
  constructor:->
    name='my secret name'
    @getName=->
      name
    null


boy= new person()


alert boy.name  #it's now private spits out undefined
alert boy.getName()

they need to be in the scope of the construct inorder for this to work. 他们需要在构造的范围内才能使其工作。 it's as close to private as you will ever get. 它与您将获得的私密性非常接近。

Problems private memebers will slow down the application. 私人问题的问题会减慢应用程序的速度。 It needs to run everytime instanced and it can't just get it from the prototype. 它需要每次运行时运行,它不能从原型中获取它。 Have fun 玩得开心

You could do something like this... 你可以这样做......

class person
  secret = 
    name : "my secret name"
  constructor:->
    x = 123
  getName: ->
    secret.name

user = new person()

console.log user.name # undefined
console.log user.getName() # "my secret name"

It is really private the downside is you will have to use a variable secret or _ or whatever you choose to reference the private variables. 这是非常私人的缺点是你将不得不使用变量secret_或任何你选择引用私有变量。

Although Javascript does not have visibility concept, you can use scopes to emulate that. 虽然Javascript没有可见性概念,但您可以使用范围来模拟它。

class Test
  privateVariable = null

  privateFunction = (obj)->
    privateVariable = obj
  constructor: (a) ->
    privateVariable = a

  publicFunction: ->
    return privateVariable

  setPrivateVariable: (obj) ->
    privateFunction(obj)

test = new Test("Test")
console.log(test.privateVariable)   # undefined
console.log(test.publicFunction())  # Test
test.setPrivateVariable("Changed!") #
console.log(test.publicFunction())  # Changed!

It is a very debatable subject. 这是一个非常值得商榷的主题。 I personally like to hide some properties and methods to make the class' contract clearer. 我个人喜欢隐藏一些属性和方法,以使类合同更清晰。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM