Переменные экземпляра частного класса CoffeeScript - PullRequest
19 голосов
/ 27 марта 2012

У меня есть следующий код CoffeeScript:

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

, который компилируется в следующий код 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;
})();

В настоящее время secret используется всеми экземплярами Person. Есть ли способ сделать secret частной переменной экземпляра в CoffeeScript?

Ответы [ 9 ]

18 голосов
/ 27 марта 2012

Я нашел решение. Я не уверен, что это лучшее решение, поэтому я по-прежнему открыт для других.

CoffeeScript:

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

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;
})();
17 голосов
/ 27 марта 2012

В CoffeeScript нет концепции закрытых членов, как в JavaScript. Существуют локальные переменные, которые вы хорошо используете в своем собственном решении , но, хотя ваше решение скрывает переменную secret от чего-либо вне функции constructor, оно также приводит к дополнительным затратам на повторное выделение inc метод для каждого экземпляра класса Person.

Ошибка, очень распространенная в сообществе JavaScript, заключается в попытке спроецировать на него несуществующие функции других языков, что, очевидно, является попыткой имитации частных пользователей. В нем нет такой концепции, и если подумать глубже, вы придете к выводу, что это было бы просто неестественно для чрезвычайно свободной динамической среды, которой является JavaScript.

Так что не тратьте свое время и производительность своего приложения на реализацию несуществующих конструкций. Просто сконцентрируйтесь на решении своей проблемы, а не проблем с отсутствием языковых возможностей.

Теперь спросите себя: что вредного в том, чтобы все участники были публичными?

Учитывая все сказанное, окончательное решение будет:

class Person
  constructor: (@name, @age, @alive) ->
    @secret = 0
  inc: -> @secret++
2 голосов
/ 27 марта 2012

Хотя это и не скрывает их по-настоящему, принято ставить префикс «частные» в нижнее подчеркивание.Идея заключается в том, что люди, потребляющие это, должны полагать, что такие члены являются деталями реализации, и им рекомендуется не использовать их.

1 голос
/ 26 июня 2012

Вот прием, который будет удовлетворять требованию большую часть времени:

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

, но вы должны иметь в виду, что: _private растет с каждым новым экземпляром (это общий массив) и вашимключ (в данном случае @dogName) должен быть уникальным для всех экземпляров.

Попробуйте

1 голос
/ 27 марта 2012

См. этот поток , вы можете заставить его работать только с помощью закрытой функции получения

0 голосов
/ 21 декабря 2014

Хотя 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!

Это очень спорный вопрос.Мне лично нравится скрывать некоторые свойства и методы, чтобы сделать контракт класса более понятным.

0 голосов
/ 27 октября 2014

Вы могли бы сделать что-то вроде этого ...

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"

Это действительно приватный недостаток, вы должны будете использовать переменную secret или _ или что угодно, чтобы ссылаться на приватныйпеременные.

0 голосов
/ 30 марта 2014

хмммммммм не совсем верно.если вам нужны частные члены, вы не можете получить приватных участников, но если вы действительно этого хотите, вы можете иметь их

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

, чтобы они работали, они должны находиться в области действия конструкции.он настолько близок к частному, насколько вы когда-либо получите.

Проблемы частных членов будут замедлять работу приложения.Он должен запускаться каждый раз, когда создается экземпляр, и он не может просто получить его из прототипа.Веселись

0 голосов
/ 02 января 2013

Вы на самом деле скрываете детали реализации, объявляя участника закрытым. Используя наследование, вы можете скрыть детали реализации, объявив «абстрактный» класс (который, насколько я знаю, фактически отсутствует в CoffeeScript) и расширив его своей собственной реализацией. Вот так:

  class bottle
        drink: ->
        empty: ->

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

теперь каждая функция, которая возвращает бутылку, должна фактически возвращать bottle_impl (скрывая этот факт от пользователя в комментариях). К сожалению, когда вы расширяете бутылку, вы не будете расширять bottle_impl, что, вероятно, не то, что вам нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...