Я уже некоторое время работаю с библиотекой прототипов, и иногда мне хочется, чтобы у меня было несколько уровней доступа (публичный, частный и защищенный). Самое близкое, что я дошел, это следующее:
SampleBase = Class.create({
/* virtual public constructor */
initialize: function(arg1, arg2)
{
// private variables
var privateVar1, privateVar2;
// private methods
var privateMethod1 = function() { }
function privateMethod2() { }
// public (non virtual) methods
this.publicNonVirtual1 = function() { return privateVar1; }
this.publicNonVirtual2 = function() { return privateVar2; }
},
// public methods (that cannot access privates)
publicVirtual1: function() { /* Cannot access privates here. */ },
publicVirtual2: function() { /* Cannot access privates here. */ }
});
Это менее чем идеально по нескольким причинам:
- Нет защищенного уровня
- У меня могут быть открытые участники, которые могут получить доступ к закрытым членам или открытым членам, которые могут быть переопределены, но не открытые участники, которые могут получить доступ к закрытым членам и могут быть переопределены.
- Мои открытые методы, которые могут быть переопределены, не являются прототипами.
Я провел некоторые поиски, но не нашел ничего, что подсказывало бы, что я могу добиться большего успеха без изменения работы прототипа. Вот некоторые из наиболее интересных ссылок:
Я видел, что можно предложить средства доступа для моих публичных виртуальных методов, используя что-то вроде этого:
Message = Class.create({
initialize: function(message)
{
var _message = message;
this.getMessage = function() { return _message; }
this.setMessage = function(value) { _message = value; }
},
printMessage: function() { console.log(this.getMessage()); },
appendToMessage: function(value) { this.setMessage(this.getMessage() + value); }
});
Это явно не будет работать как задумано. Цель состоит в том, чтобы разрешить только печать и добавление к сообщению снаружи объекта. Установщик, обеспечивающий работу виртуальной общедоступной функции, также позволяет полностью контролировать сообщение. Его можно изменить, чтобы сделать виртуальный метод немного больше, чем оболочка, следующим образом:
Message = Class.create({
initialize: function(message)
{
var _message = message;
this._printMessage = function() { console.log(_message); }
this._appendToMessage = function(value) { _message += value; }
},
printMessage: function() {this._printMessage(); },
appendToMessage: function(value) { this._appendToMessage(value); }
});
Эта новая версия ограничивает публичный доступ для этого класса, но несколько избыточна. Не говоря уже о том, что appendToMessage переопределено в подклассе, третья сторона все еще может вызвать _appendToMessage для доступа к исходному методу, который не годится.
У меня действительно есть очень грязная идея, которая сблизит меня, но это червячная банка, которую я бы предпочел не открывать. Я могу опубликовать его позже, но в то же время у кого-нибудь есть предложения объединить два типа открытых методов в один полезный тип или о том, как реализовать защищенные элементы.
EDIT:
Я подозреваю, что отсутствие обратной связи (кроме комментариев bobince ) не означает, что я прав, потому что вы не можете взять это дальше, но я думаю, что немного уточнить дело. Я не думаю, что можно приблизиться к защите других языков. Мне больше интересно знать, где лежат пределы и насколько точно мое понимание вовлеченных принципов. Однако я думаю, что было бы интересно, если не полезно, если бы мы могли заставить различные уровни защиты функционировать до такой степени, чтобы непубличные члены не отображались в цикле for ... in (или в Prototypes Object.keys, которые использует for ..in), даже если это люди, которые знают, что они делают, могут все еще нарушать правила, делая такие вещи, как работа с моими прототипами. В конце концов, как bobince говорит, что «им некого обвинять, кроме самих себя»
Теперь прокомментируем проблему, поднятую bobince :
Даже если ты сделал реальным
приватные / защищенные переменные это еще
не получу тебя полный
инкапсуляция эффективная безопасность
Граница потребует. в JavaScript
умение возиться с прототипами
встроенных типов ваши методы будут
использование дает злоумышленнику возможность
саботировать методы.
Это одно ограничение, которое я понимаю, и я, вероятно, должен был упомянуть выше. Однако я не смотрю на это с точки зрения защиты моего кода от того, кто пытается его взломать. Однако у меня есть несколько вещей, которые стоит отметить (или нуждающихся в исправлении, если я ошибаюсь):
- Только мои публичные члены уязвимы таким образом.
- Если мои общедоступные виртуальные методы «скомпрометированы» таким образом, то «скомпрометированные» методы все равно не будут иметь доступа к закрытым членам.
- Если мои публичные (не виртуальные) члены «скомпрометированы» таким образом, то, в отличие от исходной версии метода, «скомпрометированная» версия не будет иметь доступа к закрытым членам.
- Насколько я знаю, единственный способ получить доступ к закрытым членам с помощью методов, определенных вне метода initialize, - это воспользоваться ошибкой в том, как некоторые браузеры обрабатывают вызовы eval.