Pull to refresh

Comments 61

Здесь должна быть картинка про 14 конкурирующих стандартов, но её вырезала полиция банальности.

З.Ы. Кажется, я где-то уже видел JS классы на викмапах, но искать лень.
Если 14 стандартов не предоставляют того, что перечислено в заголовке статьи, то почему бы и нет.
Если вот такое придется писать
var Archive = Class.create(null, SortableMixin, function ($public, $protected, _) {
    $protected.init = function () {
        _(this).data = [3, 9, 7, 2];
    };
    $public.outData = function () {
        console.log(_(this).data);
    };
});


то «у Билла» (который на картинке) в typescript все это (кроме множественного наследования) есть и работает проще и выглядит красивее (код разрабатываемого приложения, а не самого компилятора).
Если не ошибаюсь, в TypeScript все эти protected будут protected только до стадии компиляции включительно, в runtime же все это теряется.
А в чем конкретно глубокий смысл наличия protected свойств/методов в рантайме? Вроде как эти вещи нужны лишь для удобства разработки, не более.
Например, в том, что стороннему разработчику, чтобы расширить ваш класс, не нужно изучать TypeScript и при этом, соблюдать принципы инкапсуляции.

Лучше уж выучить TypeScript, чем чужую библиотеку где классы создаются через Class.create(null, SortableMixin, function ($public, $protected, _) {

Вопрос был именно про рантайм. Зачем в рантайме это нужно?
Зачем тогда protected, если не для соблюдения инкапсуляции?

Все это не наезда ради, просто хочется разобраться, для чего может потребоваться данная библиотека и чем она лучше других решений, помимо бонуса множественного наследования (сомнительного, на мой взгляд).
Собственно, нужно для того, чтобы можно было на нативном JS писать почти настоящие классы, без необходимости в TypeScript. Всё таки JavaScript !== TypeScript. И если в каждом браузере работал TypeScript и все фронтенд разработчики писали на нём, конечно, всё было бы прекрасно.
Согласен, что для тех, кто пишет на TypeScript всё это не нужно.
В нативном JS нет классических классов и не может быть из-за прототипов. То, что ввели в ES6 — это просто сахар. С этим ничего не поделать и делать ничего не нужно. Если вам нужны «почти настоящие классы», лучше взять другой язык, который в них умеет.
Ну подытожив всё написанное в комментариях — хочешь писать хорошо и без велосипедов, пиши на TypeScript или не используй protected.
Мы в команде используем jsdoc и соглашение об именовании приватных полей через "_":
class Disposable {
/**
* @type {Boolean}
* @protected
*/
_isDisposed;
}

IDE прекрасно подхватывает
Самое адекватное решение, без лишних велосипедов. В Python подобный способ инкапсуляции уже давно существует.

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

Вам этот приват и протектед что в итоге дали? Отладку упростили? Среда разработки подчёркивает ошибки в именах методов?


Пример с примесями странный. Как отнаследоваться и примешать две примеси?

Ну как же, в Yii2 же есть, значит и в js надо притащить.
Да, я тоже делал такое.
Да, вообще все делали такое.
Лет пять-десять назад.
Я потом я сделал над собой усилие и перешёл на TypeScript.

У реализации приватных полей через WeakMap есть две проблемы. С циклическими ссылками и с просмотром значений "полей" в отладчике.


Почему вы не стали использовать символы?


var SomeClass = function() {
  var privateSymbol = Symbol("privateData");

  function SomeClass(value) {
    this[privateSymbol] = value;
  }
  SomeClass.prototype[privateSymbol] = 0;
  SomeClass.prototype.someMethod = function () {
    return this[privateSymbol];
  }
  return SomeClass;
}()

Вот так символ выглядит в консоли Хрома:


А будет ли сборщик мусора чистить protected-данные, хранящиеся в массиве за таким символом?

Не могу сказать, поскольку слабо представляю себе реализацию protected. Вы ее как-то совсем в двух словах рассказали.

UFO just landed and posted this here
Спасибо, надо будет попробовать.

Велосипед, конечно, богатый, с кучей возможностей. К сожалению, недостатки у него такие же, какие были у всех остальных:


  • Каждый фреймворк юзал свою такую вот библиотечку, стандарта де факто (как с jQuery) не получилось
  • Поддержка в IDE, в силу динамической природы трюка, никакая, а в рантайме все эти private/protected ни к чему

Присоединюсь к советующим посмотреть на TypeScript.

Уиии, 2017 год, а добрая традиция, или даже лучше сказать дисциплина, «пишем свои классы в JS» до сих пор живет!

TypeScript пожалуй лучше всего подчеркивает модификаторы доступа, тем более это важно именно при моделировании кода.
> Особенно когда переключаешься с бэкенда с использованием Yii2, на фронтенд. Ведь в Yii2 и php есть настоящие классы
Много лет назад я знакомился с php и меня выбесило отсутствие в нём перегрузки арифметических операций, как в C++. Я посчитал такое ООП неполноценным и забросил сей язык. Забросил не только поэтому, но этот эпизод стал важной последней каплей. Такие вот превратности судьбы.
Как перегрузка операторов относится к ООП?

Так же, как private/protected:)

Перегрузка — да, вещь хорошая, но необходима в меньшей степени, чем private/protected.
Предложите в каком-нибудь сообществе типа java или php отказаться от private/protected — вам покрутят у виска. В JS-сообществе же с точностью наоборот.

А предложите в питоньем сообществе private/protected — покрутят точно так же. Вопрос привычки и удобства, реальной необходимости ни в перегрузке, ни в сокрытии нет.

Когда нет перегрузки операторов, матричная или комплексная арифметика выглядит как-то так:
a.add(b); // a, b - операнды

или так
mat.add(a, b); // mat - объект, играющий роль неймспейса

а могла бы вот так
a + b

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

a * b — это векторное, скалярное или поэлементное умножение?

Ответ очевиден — на усмотрение конкретной реализации.

Речь о том, что перегрузка операторов без возможности объявления своих операторов — так себе решение. Чего только стоит перегрузка битового сдвига (<<) для стримов в C++.

Нормальное при разумном подходе и чувстве меры. В C++ есть миллион способов прострелить себе ногу, так что из того?
Чего только стоит перегрузка битового сдвига (<<) для стримов в C++.

Вы так говорите, будто это что-то плохое.

А что хорошего в том, что ты не знаешь что делает оператор пока не пройдёшься по всему дереву наследования в поисках всех его перегрузок?

В случае с protected — соглашусь, но вот private… Никто не мешает использовать процедурный или функциональный язык, где private определяет наличие или отсутствие какой-то структуры (например функции) при экспорте модуля.


… Ничего не напоминает? Модификаторы доступа — это лишь одна из возможностей реализации инкапсуляции, в JS инкапсуляция реализуется наличием/отсутствием кейворда export, например. Замените export на public, а его отсутствие на private, вот и получаем ту же самую инкапсуляцию на уровне модулей, а не на уровне класса/объект, что, к слову, местами профитнее (код интерфейса (не interface, а публичной части) тупо чище).

А давайте не будем заменять «папу» на «маму» и будем читать ветку полностью? Речь шла конкретно о ключевых словах protected/private и возможности их использовании вне ООП и даже объектного подхода.

А давайте не будем принимать совпадения за закономерности? Сегодня "вне объектного подхода" таких ключевых слов нет — а завтра кто-нибудь придумает новый чистый функциональный язык программирования, где эти слова будут присутствовать.

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

Не надо так.

Ну не правда же, я просто провёл параллель с JS и намекнул, что private есть и в JS, просто он иначе называется и иначе работает, а заодно сделал намёк, что этот "private" есть и в других не ОО языках, иногда даже так и называется, например в Ada или Fortran


UPD. И согласился по поводу protected, т.к. не припомню не ОО языков, где был бы подобный модификатор, хотя придумать можно.

Вы шутите, да? Я все это время рассказывал, что в C++ protected/private имеют отношение к ООП, а перегрузка операторов — нет.

Весь остальной флуд меня изумляет своей беспочвенностью =)

Ну с моей стороны диалог выглядит так (насколько я его понял):


  • Доминик: У каждого языка, мол, свои плюшки, мне, например, не понравился ООП в пыхе, т.к. там нет перегрузки операторов.
  • Вы: Перегрузка операторов — это не ООП
  • k12th: Так статья тоже не про ООП, а просто частности переноса одного в другое
  • Вы: Да ладно, модификаторы как раз про ООП.

А дальше моё замечание, мол, ну почему же. Если я кого-то не совсем правильно понял, прошу понять и простить =)

Вот серьезно, такие библиотеки должны умереть.
Мало вам классов в JS берите Dart там есть все и даже больше, без вот этих ваших костылей и прочего.
Dart только сам уже почти мёртв.
Из реальных альтернатив только TypeScript, с его реализацией всего этого дела на этапе компиляции.
Согласен, что велосипед и очередная библиотека. Лично для меня весь этот проект — показатель того, что на чистом JS можно реализовать настоящий protected, пусть и несколько нетривиально.
я не стал бы говорить что Dart мертв, насколько мне видно, он все так же развивается и поддерживает. Другой вопрос что он не получил популярности и у него не очень понятное будущее. Но это куда лучше чем вот такая библиотека, потому что будущее этой библиотеки еще туманней чем у Darta.

Я так и не понял зачем вам настоящие приватные и защищенные методы в js? Для контроля кода в момент разработки достаточно писать jsdoc и тогда нормальная IDE сама сообщит что это за метод и как его следует использовать. Для иллюзии защищенности кода в момент выполнения, так это только иллюзия и лишнее переосложнение системы, еще не раз будет напоминать себе при отладке.
По поводу необходимости protected. Взгляните на какой-нибудь класс, реализующий, например, ActiveRecord. Protected очень помогает отделять методы которые можно вызывать из любого места, от тех, которые можно переопределить только расширяя класс. Наследование без protected это большой недостаток ООП в этом языке. Я бы не стал говорить что они не нужны.
Другое дело, что JS из коробки это не предоставляет, а обходные пути либо сложные (как представлено здесь), либо работают только в определённой среде (предупреждения IDE, ошибки компиляции TypeScript). Проблема в том, что большинство библиотек написаны на чистом JS, а не на TypeScript. И не факт, что все работают в IDE с соблюдением всех рекомендаций.
Ну почему все пытаются воткнуть в JS ООП (в терминах Java/C++)? Тут прототипное наследование. Какие protected? Ну нет их тут и быть не может.
Если вы хотите, чтобы вам компилятор жаловался, что вы обращаетесь к private/protected полю снаружи, так это вам компилируемый язык нужен, при чем тут JS-то вообще?
Ну почему все пытаются воткнуть в JS ООП (в терминах Java/C++)? Тут прототипное наследование.

Потому что прототипное наследование в реализации JS — это грусть и погибель для поддержки более или менее сложных приложений, очевидно. Тренд в JS сейчас — это спрятать реальный, злой JS поглубже, обложившись разного рода трансляторами.
В чем проблема? Просто не пишите на js, сейчас достаточно транс-компилируемых языков.
Если кому-то не нравится ASM, то он на нем и не пишет, с js тоже самое.
В чем проблема? Просто не пишите на js

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

транс-компилируемых языков

Транслируемых же, на выходе обычный текст.
Как такой код дебажить, например?

Можно дебажить с включенным «Source Maps».

Транслируемых же, на выходе обычный текст.

Для source-to-source есть отдельные термины
Я все же с Вами не соглашусь.
Мое мнение все же останется прежним, что правильней это помечать jsdoc`ом приватные/защищенные методы, чем реализовывать это через библиотеки.
Что касается сторонних библиотек, то это проблема библиотек что там комментариев к коду нет, значит библиотека «не очень» и лучше воздержаться от ее использования.
Что касается IDE то не надо думать о всех, нужно думать о себе. Настройте IDE что бы оно понимало jdoc, помечайте методы jsdoc'ом, а те кто пишут в блокноте должны либо читать ваш код и помнить головой где какой метод или использовать IDE.
добавление к предыдущему моему комментарию:
Так же можно ввести договоренность в именовании методов, например:
Методы которые начинаются на "$" это приватные, а "$$" это защищенные.

И это во много раз проще в поддержке и отладке, чем копаться потом в стектрейсе который будет захламлен библиотечными функциями.
Так же это проще для стороннего человека, ему не нужно въезжать в детали реализации библиотеки, достаточно только узнать о принятой методологии именовании методов.
Sign up to leave a comment.

Articles