2012-03-27 2 views
19

У меня есть следующий код: CoffeeScriptCoffeeScript частного класса Переменные экземпляра

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?

ответ

17

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

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

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

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

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

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

Общепринято использовать соглашения об именах для обозначения «частных» переменных. Подобно Python, это обычно обозначается '_var', то есть' _secret' в этом случае. –

+1

@AaronDufour То, что вы предлагаете, - это еще одна попытка подражать функции частных членов. Я хочу сказать, что разработчик JavaScript должен освободить свой разум от такой концепции, потому что, в конце концов, все подобные решения могут стать чрезмерным применением без каких-либо практических целей. –

+21

Он не подражает частным членам; это только делает более понятным, как класс предназначен для использования. Вызов переменной 'secret', вероятно, достаточно, но префикс подчёркивания является более общим решением. Это особенно полезно, если класс подвергается воздействию третьих сторон. –

18

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

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

Обратитесь к this thread, вы могли бы только заставить его работать через closured функцию геттера

2

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

1

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

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) должны быть уникальными экземплярами.

Try it

0

Вы на самом деле скрываются детали реализации, объявив членом частного.Используя наследование, вы можете скрыть детали реализации, объявив «абстрактный» класс (который, как я знаю, на самом деле не существует в 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 (скрывая этот факт от пользователя в комментариях). К несчастью, когда вы расширяете бутылку, вы не будете расширять бутылку, которая, вероятно, не та, что вы хотите.

0

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

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

доказательство в пудинге http: // coffeescript.орг/# попробовать:% 20class% 20person% 20% 0A% 20% 20% 20% 20% 20% 20constructor% 3A-% 3E% 0A% 20% 20% 20% 20% 20% 20% 20% 20name% 3D 'мой% 20secret% 20name' % 0A% 20% 20% 20% 20% 20% 20% 20% 20% 40getName% 3D-% 3E% 0A% 20% 20% 20% 20% 20% 20% 20% 20 % 20% 20name% 0A% 20% 20% 20% 20% 20% 20% 20% 20null% 0A% 20% 20% 20% 20% 0A% 20% 20% 20% 20% 0A% 20% 20% 20 % 20boy% 3D% 20new% 20person()% 0A% 20% 20% 20% 20% 0A% 20% 20% 20% 20% 0A% 20% 20% 20% 20alert% 20boy.name% 20% 20% 23it-х % 20now% 20private% 20spits% 20out% 20undefined% 0A% 20% 20% 20% 20alert% 20boy.getName() –

0

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

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

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

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

Смежные вопросы