Модераторы: Sardar, Aliance

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Наследование и состояние над-класса 
V
    Опции темы
Се ля ви
Дата 12.6.2008, 15:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java/SOAрхитектор
****


Профиль
Группа: Модератор
Сообщений: 2016
Регистрация: 5.6.2004
Где: place without tim e and space

Репутация: 5
Всего: 127



Цитата(dsCode @  11.6.2008,  20:48 Найти цитируемый пост)
Се ля ви, не могу не отдать должное за такие подробные блоги о Ваших исследованиях =) Однако, боюсь, вряд ли это столь актуально в ООП языке с динамическими mutable-объектами.

Я описывал чуть выше - весь мой опыт работы в крупных проектах свидетельствует, что без разделения кода на зоны ответственности эффективная кооперация большого количества разработчиков практически невозможна. В итоге максимум, на что можно рассчитывать - это код, который пишут 2-3 человека, из которых один главный, а эффективность работы остальных сильно снижена из-за того, что они должны постоянно разбираться в коде первого что бы что-то к нему добавлять.
Как раз на разделение зон ответственности направлен ряд приёмов в Java, которые я и хочу сюда привнести.

Цитата(dsCode @  11.6.2008,  20:48 Найти цитируемый пост)
версия 2.0. сулит нам классы (с private'ами, public'ами и т.д.), но классы там будут так же динамическими (хотя, может и будут разграничения на статические и динамические) - все так же можно будет достучаться до прототипов и поменять все, что нужно. Это я к тому, что концепции, подобной строго-статичным классам из Java, C++, PHP здесь не будет.

К сожалению, я не могу с вами согласиться. Т.е. если это и сделают, то очень не скоро их использование станет стандартом де-факто. Да за примером далеко ходить не надо - вы же сами пишете:
Цитата(dsCode @  11.6.2008,  20:48 Найти цитируемый пост)
А классы в 2.0. будут в концепции, более схожей с Python'ом (нежели с Java) - там так же, как и в JS (кстати, именно из-за любви к JS, мне очень понравился Питон, хотя до этого (и по долгу службы) на серверной стороне я занимался PHP)

значит, вы занимались PHP, а какой, позвольте спросить, версии? Ваш переход на Python состоялся до или после выхода PHP 5, в котором появились довольно-таки хорошие ОО-средства работы с кодом? Я, конечно, не в курсе ваших мотивов, но, к сожалению, Python тоже пока весьма слабый игрок на поле крупных корпоративных приложений (хотя многие надеются, что со временем станет) - и брать с него пример по-этому в таких вещах несколько преждевременно - он ещё не настолько успел себя зарекомендовать.

Так же и с JS 2.0 - у меня большие сомнения, что его моментально реализуют и он моментально распространится по 90-95% аудитории интернет-пользователей. А пока не настанет такой момент, его использование будет просто забавой программистов на досуге - не более того, ибо ни один денежный заказчик с этими технологиями связываться не рискнёт. По моим прогнозам, после принятия этого стандарта до этого момента пройдёт года 3 - не меньше. Эти три года вы предлагаете лишь мечтательно воздыхать в предвкушении? Если так - не имею возможности составить вам в этом компанию smile

Когда вышел PHP 5 и где рынок хостеров, наперебой предлагающих размещать у них сайты, написанные на нём, по-дешевле? Сколько их сейчас и как быстро появлялись те, что есть? Нет рынка - считай, нет и технологии, есть только игрушки...

Ну а насчёт строго-статичных концепций - я не очень в курсе про С++ и PHP, но в Java есть такая штука - Reflection API - которая позволяет работать с классами как с mutable, делая с ними всё, что угодно - считай, если бы все программисты постоянно использовали Reflection API, эта ситуация во многом бы и напоминала реалии программмирования на JS. Просто при программировании на Java не принято использовать Reflection API, он используется только для специфичных задачь, например сетевыми взаимодействиями и инструментальными средствами для облегчения разработки.
Примерно тот же подход я предлагаю внести и сюда - некоторое соглашение, что мы не используем без крайней на то необходимости метод  "eval" и динамическое создание/удаление/изменение методов, а так же стараемся по-минимуму использовать public-поля и, если уж используем, то с сохранением их типа и других соглашений в отношении них.
Цитата(dsCode @  11.6.2008,  20:48 Найти цитируемый пост)
Просто не понятно - от кого эти защиты? От программистов, которые будут использовать Вашу библиотеку псевдо-классов? Так они и так умеют программировать и понимают, что к чему. 

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

Цитата(dsCode @  11.6.2008,  20:48 Найти цитируемый пост)
А Рич-Эпликейшенс (и подобные GMail, которые Вы приводили) пишутся и без имитаций private'ов.

Ну, во-первых здесь не имитация private`ов, а самые настоящие private`ы - попробуте-ка обратиться к свойству "_privateField1" напрямую - ничего не выйдет, оно замкнуто - так что это самое настоящее private-поле, никакой "имитации". Просто реализовано оно через замыкание.

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

Цитата(dsCode @  12.6.2008,  13:06 Найти цитируемый пост)
для обеспечения легковесных объектов (особенно для Rich-Applications) нам не нужны замкнутые var'ы для имитации именно private'ов из статично-классовых языков, а можно обойтись именованием

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


--------------------
  )
 (
[_])
проф. блог

Кролики думали, что занимаются любовью, а на самом деле их просто разводили...
PM MAIL WWW Skype GTalk   Вверх
dsCode
Дата 12.6.2008, 17:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 565
Регистрация: 8.9.2007
Где: Saint-Petersburg

Репутация: 19
Всего: 26



Цитата(Се ля ви @  12.6.2008,  15:09 Найти цитируемый пост)
значит, вы занимались PHP, а какой, позвольте спросить, версии?

поправка - занимаюсь и в данный момент (хотя, в последнее время - больше фронтэндом, а именно - JS), по версиям - начиная с 3-ей и до текущей 5.2.6. А Питоном я занимаюсь только "на досуге" (пока).

Цитата(Се ля ви @  12.6.2008,  15:09 Найти цитируемый пост)
Я, конечно, не в курсе ваших мотивов, но, к сожалению, Python тоже пока весьма слабый игрок на поле крупных корпоративных приложений (хотя многие надеются, что со временем станет) - и брать с него пример по-этому в таких вещах несколько преждевременно - он ещё не настолько успел себя зарекомендовать.

Мотивы? Всего лишь показал схожесть с JS и, как там реализованы private-свойства. Питон идет в составе любого нормального  дистрибутива Linux. Кстати, Java мне также очень нравится, поэтому не подумайте, что я собираюсь тут холиворить о том, какой язык лучше. Я вправе использовать все, какие потребуются [с учетом их специфики для достижения оптимальных результатов].

Цитата(Се ля ви @  12.6.2008,  15:09 Найти цитируемый пост)
есть такая штука - Reflection API

Я в курсе =) и в PHP она достаточно хорошо организована. Более того, в Питоне эта "штука" тоже есть. Анализ-то - понятно, но  скажите, как при помощи рефлекции (или интроспекции) можно добавить новое свойство / метод в класс и, чтобы это свойство отобразилось на всех уже инстанцированных объектах? [я просто не использую ее каждый день, и не слышал, что так можно smile]

Цитата(Се ля ви @  12.6.2008,  15:09 Найти цитируемый пост)
слабовольные программист начнёт активно работать с этими значениями напрямую

Кто такой слабовольный программист? Зачем он начнет это делать? Вот это, как раз-таки, игрушки. Если ему так это захочется, он пойдет, переименует свойство в public и будет менять его дальше напрямую. Нет-нет, я знаю, что такое инкапсуляция и зачем она нужна. В разных языках - разные подходы, и Питон я приводил лишь для примера альтернативного подхода - пусть "псевдо-инкапсулируещего", но тем не менее. И это не значит, что я против инкапсуляции в Java, PHP, C++ - вовсе нет, не делайте неверных выводов.

Цитата(Се ля ви @  12.6.2008,  14:09 Найти цитируемый пост)
Да нет же, в том-то и весь фокус

Ах, пардон, я не заметил return new function() {. Ну, т.е. получился wrapper который должен дублировать имена приватных свойств (рабочих приватных свойств) в своем скопе (только с двумя подчеркиваниями). Каждый объект имеет собственные свойства getPrivateField1 и setPrivateField1 (и т.д.) - пусть это теперь не "цельные тяжелые куски", а лишь ссылки на методы контейнера, но все же - они свои, в то время как семантически одинаковым методам место в прототипе (но здесь получается выигрыш в скорости - посредством делегирования медленней получить результат, чем вызвав свой метод, который "под боком", но проигрыш в ресурсах).

Только я боюсь, что кто-то скажет (когда увидит вот это в каждом методе):

Код

this.privateState._get();

... bla-bla ...                
                
this.privateState._set();


"Блин, а ... никто не знает, зачем в каждом методе здесь вот эти две строчки всегда надо писать? Инкапсуляция? Да ладно?... Хм.. Оригинальный подход..". Не кажется ли Вам, что, забудь все тот же "слабовольный программист" (Ваше определение) написать загрузку этих инкапсулированных строк, он еще больше трудно-уловимых багов наделает?

P.S.: еще раз, тем не менее, я в состоянии оценить проделанную работу. smile 


Это сообщение отредактировал(а) dsCode - 12.6.2008, 17:29


--------------------
the .code inside
:my music
PM MAIL WWW ICQ Jabber   Вверх
AKS
Дата 12.6.2008, 17:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Участник форума
**


Профиль
Группа: Участник
Сообщений: 725
Регистрация: 20.9.2006

Репутация: 27
Всего: 52



Се ля ви, да, действительно, теперь в порядке! Стал разбираться с кодом – появился все тот же вопрос. Вы ушли от более простого к более сложному. Если раньше в теле конструктора для каждого экземпляра создавалась пара геттер/сеттер для доступа к локальной переменной, то теперь для каждого экземпляра создается объект privateState плюс все та же самая парочка геттер/сеттер, являющаяся теперь методами этого объекта. Вопрос в следующем – Вы просто смирились с тем, о чем писали ранее: "тут получается, что я расточительно создаю каждый раз новый объект-функцию"? 
Ну и еще не могу удержаться, чтобы не задать буквально парочку вопросов. У Вас сейчас _super – это св-во глобального объекта. Каждый конструктор в момент вызова будет присваивать ей новое значение. Это так хитро задумано? smile И еще, в чем смысл вот такой проверки if (arguments[0] != null)? Получилась эдакая "защита" от всё тех же дураков, чтобы не передавали в конструктор первым аргументом null (если null, то принципиально фиг им, а не инициализация параметров). smile


dsCode, я просто дословно воспринял это ваше "obj.getA() будет работать, но obj.a - уже нет". Подумал, как же так сделать, чтобы obj.a было доступно через obj.getA(), и никак иначе. smile

PM MAIL   Вверх
dsCode
Дата 12.6.2008, 17:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 565
Регистрация: 8.9.2007
Где: Saint-Petersburg

Репутация: 19
Всего: 26



Цитата(AKS @  12.6.2008,  17:23 Найти цитируемый пост)
создается объект privateState плюс все та же самая парочка геттер/сеттер, являющаяся теперь методами этого объекта

объект, который содержит скоп всех верхних "породителей" (ведь и _privateField1 и _privateField2 оседают в скоп-чейне медотов this._get и this._set (которые всегда свои для privateState'a), так?). И помимо этих двух геттеров / сеттеров, есть еще и ссылка-геттер, и ссылка-сеттер, которые хоть и ссылки, но имеют значения, а значит - "жрут ресурсы".

Это сообщение отредактировал(а) dsCode - 12.6.2008, 17:40


--------------------
the .code inside
:my music
PM MAIL WWW ICQ Jabber   Вверх
AKS
Дата 12.6.2008, 17:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Участник форума
**


Профиль
Группа: Участник
Сообщений: 725
Регистрация: 20.9.2006

Репутация: 27
Всего: 52



Цитата(dsCode @  12.6.2008,  17:37 Найти цитируемый пост)
которые всегда свои для privateState'a), так?

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

PM MAIL   Вверх
dsCode
Дата 12.6.2008, 18:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 565
Регистрация: 8.9.2007
Где: Saint-Petersburg

Репутация: 19
Всего: 26



AKS, да это-то я вижу =) Я просто хотел поинтересоваться про скоп-чейн, который хранит все эти замкнутые var'ы. Скоп внешней функции приплюсовывается к скопу внутренней при ее создании. Получается, что и this._get и this._set имеют скоп с var'ами _privateField1 и _privateField2 (поскольку используют эти var'ы). В то же время, privateState всегда новый (в виду new). Получается куча этих скопов, связанных с this._get и this._set будет жить при создании нового объекта (или там ссылка на, может быть, какой-то общий скоп-чейн?).

Это сообщение отредактировал(а) dsCode - 12.6.2008, 18:16


--------------------
the .code inside
:my music
PM MAIL WWW ICQ Jabber   Вверх
AKS
Дата 12.6.2008, 19:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Участник форума
**


Профиль
Группа: Участник
Сообщений: 725
Регистрация: 20.9.2006

Репутация: 27
Всего: 52



dsCode, там получается следующее. Сначала идет вот это: F._class = new F;. В момент первого вызова конструктора F выполняется та часть его кода, которая в else. Все, что там создается - там же и остается. Все методы хранят ссылку на variable-объект, созданный в этот момент (момент первого вызова F). Переменная _privateField1 - одна на всех. Ее поиск будет осуществляться так (VO - это variable-объект функций): _get VOVO анонимной функции, createPrivateState VOF VO (тот, что был создан в момент первого вызова).
PM MAIL   Вверх
dsCode
Дата 12.6.2008, 19:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 565
Регистрация: 8.9.2007
Где: Saint-Petersburg

Репутация: 19
Всего: 26



AKS, ага... Т.е. на момент первого вызова (фактически - на момент определения _get / _set, которые используют _privateField1 из скопа F), будет однозначно определена цепь скопов, по которым будет производиться поиск _privateField1 при вызове _get - не зависимо от того, что this.createPrivateState всегда возвращает результат новой анонимной функции. Эмм.... Ну да, в любом случае _privateField1 принадлежит VO(F) и будет искаться в нем. Спасибо =)


--------------------
the .code inside
:my music
PM MAIL WWW ICQ Jabber   Вверх
Се ля ви
Дата 12.6.2008, 23:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java/SOAрхитектор
****


Профиль
Группа: Модератор
Сообщений: 2016
Регистрация: 5.6.2004
Где: place without tim e and space

Репутация: 5
Всего: 127



dsCode,
Цитата(dsCode @  12.6.2008,  17:17 Найти цитируемый пост)
занимаюсь и в данный момент (хотя, в последнее время - больше фронтэндом, а именно - JS), по версиям - начиная с 3-ей и до текущей 5.2.6. А Питоном я занимаюсь только "на досуге" (пока).

А, ну тогда вот это прямо по адресу:
Цитата(Се ля ви @  12.6.2008,  15:09 Найти цитируемый пост)
Когда вышел PHP 5 и где рынок хостеров, наперебой предлагающих размещать у них сайты, написанные на нём, по-дешевле? Сколько их сейчас и как быстро появлялись те, что есть? Нет рынка - считай, нет и технологии, есть только игрушки...


Цитата(dsCode @  12.6.2008,  17:17 Найти цитируемый пост)
Мотивы? Всего лишь показал схожесть с JS и, как там реализованы private-свойства. Питон идет в составе любого нормального  дистрибутива Linux. Кстати, Java мне также очень нравится, поэтому не подумайте, что я собираюсь тут холиворить о том, какой язык лучше. Я вправе использовать все, какие потребуются [с учетом их специфики для достижения оптимальных результатов].

Это замечательно. Я, честно говоря, тоже немного сталкивался с Python`ом и тоже испытываю к нему симпатию. Особенно нехватает в Java его фишки с блоками с помощью табуляций - настолько это было бы удобно!..
Хотя вообще-то, больше всех мне нравится язык SmallTalk - это вообще божественный язык программирования, жаль, что ни одна крупная корпорация не взялась его продвигать и писать под него библиотеки на все случаи жизни, как содружество Java Community Process для Java, Microsoft для C# и Borland для Object Pascal... :( Но это уже совсем другая тема.

Цитата(dsCode @  12.6.2008,  17:17 Найти цитируемый пост)
скажите, как при помощи рефлекции (или интроспекции) можно добавить новое свойство / метод в класс и, чтобы это свойство отобразилось на всех уже инстанцированных объектах? [я просто не использую ее каждый день, и не слышал, что так можно smile]

Я не очень подробно занимался этим вопросом. Я слышал, что это реализуется на этапе подгрузки класса - можно переопределить ClassLoader и при подгрузке класса в JVM поменять в нём всё что угодно. Однако про такие приёмы, как изменение свойств класса, что бы они отразились на уже созданных экземплярах я не слышал - но, возможно, есть и такие, я просто не достатьчно подробно занимался этим вопросом. Можете спросить об этом в соответствующем разделе Vingrad`а - у нас по Java очень сильные специалисты.

Цитата(dsCode @  12.6.2008,  17:17 Найти цитируемый пост)
получился wrapper который должен дублировать имена приватных свойств (рабочих приватных свойств) в своем скопе (только с двумя подчеркиваниями). Каждый объект имеет собственные свойства getPrivateField1 и setPrivateField1 (и т.д.) - пусть это теперь не "цельные тяжелые куски", а лишь ссылки на методы контейнера, но все же - они свои, в то время как семантически одинаковым методам место в прототипе (но здесь получается выигрыш в скорости - посредством делегирования медленней получить результат, чем вызвав свой метод, который "под боком", но проигрыш в ресурсах).

Не столько в этом, сколько в том, что теперь объект-функция (ведь каждая функция - это объект) теперь создаётся один раз и все объекты просто на неё ссылаются - на одну и ту же.
Я сначала хотел, действительно, реализовать их через прототип, но тогда я не смог бы продолжать цепочку наследования дальше - т.е. не смог бы обеспечить каждый объект F своим собственным экземпляром E - поскольку прототип у класса был бы один и нельзя было бы реализовать скозную (через класс) связь объекта с объектом предка - задача, с которой началась эта тема. Так что пришлось реализовывать так.

Цитата(dsCode @  12.6.2008,  17:17 Найти цитируемый пост)
Только я боюсь, что кто-то скажет (когда увидит вот это в каждом методе):
Код
this.privateState._get();

... bla-bla ...                
                
this.privateState._set();


"Блин, а ... никто не знает, зачем в каждом методе здесь вот эти две строчки всегда надо писать? Инкапсуляция? Да ладно?... Хм.. Оригинальный подход..".

Фактически, это - паттерн. Обычно в комментариях указывается, что "это и то было реализовано с использованием паттерна такого-то...". И что бы разобраться в чужом коде, если натыкаешься на упоминание о паттерне в комментариях, очень полезно бывает посмотреть описание этого паттерна в каталоге паттернов - тогда все вопросы о страннастях кода отпадают. По крайней мере так принято в мире Java. Здесь так же может помочь только этот подход.

Цитата(dsCode @  12.6.2008,  17:17 Найти цитируемый пост)
Не кажется ли Вам, что, забудь все тот же "слабовольный программист" (Ваше определение) написать загрузку этих инкапсулированных строк, он еще больше трудно-уловимых багов наделает?

Совершенно верно! По-этому я и говорю:
Цитата(Се ля ви @  12.6.2008,  01:58 Найти цитируемый пост)
На последок маленький совет. Думаю, что разрабатывать какой-то новый функционал будет заметно удобнее с использованием простой модели наследования, а уже потом, когда всё в порядке, только не устраивает объём съедаемой памяти и скорость выполнения, можно переделывать её в эту, заметно более сложную модель.


AKS,
Цитата(AKS @  12.6.2008,  17:23 Найти цитируемый пост)
Вы ушли от более простого к более сложному. Если раньше в теле конструктора для каждого экземпляра создавалась пара геттер/сеттер для доступа к локальной переменной, то теперь для каждого экземпляра создается объект privateState плюс все та же самая парочка геттер/сеттер, являющаяся теперь методами этого объекта.

Да, теперь это просто пара ссылок на существующие вне объекта методы.

Цитата(AKS @  12.6.2008,  17:23 Найти цитируемый пост)
Вопрос в следующем – Вы просто смирились с тем, о чем писали ранее: "тут получается, что я расточительно создаю каждый раз новый объект-функцию"?

Почему же смирился? Как раз наоборот - каждая функция-то теперь одна единственная, на неё только ссылок много, но ссылки памяти практически не занимают, в отличие от объектов, на которые они ссылаются. Представьте, что у вас 100 000 экземпляров одного конструктора с одной парой геттер/сеттер. Если он реализован в простой модели, то это означает, что у нас появляется ещё 100 000 объектов-функций геттеров и 100 000 объектов-функций сеттеров. А в данной модели 100 000 ссылок на геттер и 100 000 ссылок на сеттер - что будет тяжелее обработать браузеру? Это, конечно, зависит от того, насколько хорошо реализованы ссылки в браузере, но думаю, что объём памяти, используемой при таких раскладах в первом и во втором случае просто несоизмерим - второй подход тут просто единственно-возможен.


Цитата(AKS @  12.6.2008,  17:23 Найти цитируемый пост)
Ну и еще не могу удержаться, чтобы не задать буквально парочку вопросов. У Вас сейчас _super – это св-во глобального объекта. Каждый конструктор в момент вызова будет присваивать ей новое значение. Это так хитро задумано?

Это ошибка, спасибо, что подсказали. Действительно, нужно поставить var, уже исправил. Кстати раз это private-поле, то хранить его нужно в объекте privateState - а тогда и передавать его туда нужно параметром для правильной инициализации, что я и сделал:
Код
        if (this.constructor._class) {
            //Get privateState object
            this.privateState = this.constructor._class.createPrivateState(this.constructor.prototype);

            this.constructor.prototype = new this.constructor.prototype.constructor;

и потом:
Код
            this.createPrivateState = function(super) {
                return new function() {
                    var _inner = 0,
                        __super = super,
                        __privateField1,
                        __privateField2;
                        
                    this._get = function() {
                        if (_inner++ == 0) {
                            _super = __super;
                            _privateField1 = __privateField1;
                            _privateField2 = __privateField2;
                        }
                    };
                    
                    this._set = function() {
                        if (_inner-- == 1) {
                            __super = _super;
                            __privateField1 = _privateField1;
                            __privateField2 = _privateField2;
                            
                            _super =
                            _privateField1 =
                            _privateField2 = null;
                        }
                    };
                };
            }

Цитата(AKS @  12.6.2008,  17:23 Найти цитируемый пост)
И еще, в чем смысл вот такой проверки if (arguments[0] != null)? Получилась эдакая "защита" от всё тех же дураков, чтобы не передавали в конструктор первым аргументом null (если null, то принципиально фиг им, а не инициализация параметров).

Это проверка, переданы ли аргументы. Просто инициировать объект сразу после создания имеет смысл лишь тогда, когда ему был передан хотя бы один аргумент - иначе это означает, что объект создаётся для будущего наследника. Просто в нашем простом случае у нас так и так нету параметров, так что и в случае отсутствия даже одного первого аргумента мы тоже должны вызвать метод "init". Так что первая строчка "для порядку" - что бы когда кто-то будет copy/paste`ить этот код, то ему было просто удобнее вписывать свой код в те места, где сейчас по сути заглушки smile


--------------------
  )
 (
[_])
проф. блог

Кролики думали, что занимаются любовью, а на самом деле их просто разводили...
PM MAIL WWW Skype GTalk   Вверх
dsCode
Дата 13.6.2008, 00:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 565
Регистрация: 8.9.2007
Где: Saint-Petersburg

Репутация: 19
Всего: 26



Се ля ви
Цитата(Се ля ви @  12.6.2008,  23:54 Найти цитируемый пост)
Хотя вообще-то, больше всех мне нравится язык SmallTalk

В Python ООП модель заимствованна именно из SmallTalk (хотя на Смолтоке я ни разу не программировал - не доводилось (как ни странно - даже ради интереса), но, уверен, что мне бы тоже понравился (в виду того, что он является и прародителем JavaScript'a). Может, как-нить гляну на досуге). Кстати, есть реализация Jyton - реализация Питона на Java, выполняющаяся через JVM, таким образом есть возможность использовать классы Java. Ну ладно, не о Питоне речь - опять отвлекася =)

Цитата(Се ля ви @  12.6.2008,  23:54 Найти цитируемый пост)
Однако про такие приёмы, как изменение свойств класса, что бы они отразились на уже созданных экземплярах я не слышал - но, возможно, есть и такие, я просто не достатьчно подробно занимался этим вопросом. Можете спросить об этом в соответствующем разделе Vingrad`а - у нас по Java очень сильные специалисты.

Не сомневаюсь, что сильные, да только мне еще сильнее "кажется", что нет такого ни в Java, ни в C++, ни в PHP (но есть в JavaScript, Python, Ruby (скорей всего, не проверял) и Smalltalk (также интуитивно предполагаю)).

Цитата(Се ля ви @  12.6.2008,  23:54 Найти цитируемый пост)
Фактически, это - паттерн. Обычно в комментариях указывается, что "это и то было реализовано с использованием паттерна такого-то...". И что бы разобраться в чужом коде, если натыкаешься на упоминание о паттерне в комментариях, очень полезно бывает посмотреть описание этого паттерна в каталоге паттернов - тогда все вопросы о страннастях кода отпадают. По крайней мере так принято в мире Java. Здесь так же может помочь только этот подход.

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

Ну а теперь обратно к вопросу (и AKS правильно подметил): пусть getPrivateField1 теперь будет ссылкой, но createPrivateState у каждого объекта свой (вы же сами меня поправили, когда я не досмотрел, что состояния у объектов - свои), и ввиду return new function() { ... } так же будут свои _get и _set - т.е. остается все та же "парочка" (только она теперь в другом месте - внутри createPrivateState), плюс к этому две ссылки - getPrivateField1 и setPrivateField1.


Это сообщение отредактировал(а) dsCode - 13.6.2008, 01:12


--------------------
the .code inside
:my music
PM MAIL WWW ICQ Jabber   Вверх
Се ля ви
Дата 13.6.2008, 02:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java/SOAрхитектор
****


Профиль
Группа: Модератор
Сообщений: 2016
Регистрация: 5.6.2004
Где: place without tim e and space

Репутация: 5
Всего: 127



Цитата(dsCode @  13.6.2008,  00:59 Найти цитируемый пост)
В Python ООП модель заимствованна именно из SmallTalk (хотя на Смолтоке я ни разу не программировал - не доводилось (как ни странно - даже ради интереса), но, уверен, что мне бы тоже понравился (в виду того, что он является и прародителем JavaScript'a). Может, как-нить гляну на досуге). Кстати, есть реализация Jyton - реализация Питона на Java, выполняющаяся через JVM, таким образом есть возможность использовать классы Java. Ну ладно, не о Питоне речь - опять отвлекася =)

Да и PHP есть реализация и вообще в JDK6 есть механизм скриптинга - можно множество языков реализовывать и использовать.

Цитата(dsCode @  13.6.2008,  00:59 Найти цитируемый пост)
Ну а теперь обратно к вопросу (и AKS правильно подметил): пусть getPrivateField1 теперь будет ссылкой, но createPrivateState у каждого объекта свой (вы же сами меня поправили, когда я не досмотрел, что состояния у объектов - свои), и ввиду return new function() { ... } так же будут свои _get и _set - т.е. остается все та же "парочка" (только она теперь в другом месте - внутри createPrivateState), плюс к этому две ссылки - getPrivateField1 и setPrivateField1.

Насчёт createPrivateState - что значит - у каждого объекта свой? Это метод класса, который просто возвращает нам объект. Этот объект у каждого свой, но метод-то один smile

Ну да, согласен, у нас появляются пара _get и _set для каждого объекта и в случае с одним полем это выглядет одинаково, но одно поле - это только для демонстрации, подразумевается-то, что у каждого объекта по многу свойств и, соответственно, много пар геттер/сеттер и тогда при таком подходе мы меняем всё это множество методов на одну реализацию методов и _get с _set`ом для подмены контекста класса. Выигрыш будет именно при наличии большого количества методов.


--------------------
  )
 (
[_])
проф. блог

Кролики думали, что занимаются любовью, а на самом деле их просто разводили...
PM MAIL WWW Skype GTalk   Вверх
AKS
Дата 13.6.2008, 06:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Участник форума
**


Профиль
Группа: Участник
Сообщений: 725
Регистрация: 20.9.2006

Репутация: 27
Всего: 52



Се ля ви, я, конечно, не очень много видел в своей жизни, но хотелось бы написать, что такой конструкции не встречал. Получилась не плохая тема для блога (Вы ведь, вроде, хотели статью писать). Теперь единственное, что может напугать, так это: "подразумевается-то, что у каждого объекта по многу свойств". Т.е. если будет много св-в, то конструктор будет выглядеть громоздко. Но это, наверняка, можно обойти, используя, например, массивы или еще как-нибудь... 
Ну а в общем - мне нравится (хоть и не испытывал толком, но зато уже "привык" к ходу вашей мысли smile ). ;)
PM MAIL   Вверх
AKS
Дата 13.6.2008, 06:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Участник форума
**


Профиль
Группа: Участник
Сообщений: 725
Регистрация: 20.9.2006

Репутация: 27
Всего: 52



Забыл про проверку аргументов написать. ;)
Цитата(Се ля ви @  12.6.2008,  23:54 Найти цитируемый пост)
Это проверка, переданы ли аргументы.

Вот это: if (arguments[0] != null) не проверка "переданы ли аргументы". Это проверка "нет ли у первого аргумента значений null/undefined". Поэтому и спросил - это дизайн такой на запрет передачи подобных значений или еще что-то.
PM MAIL   Вверх
dsCode
Дата 13.6.2008, 11:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 565
Регистрация: 8.9.2007
Где: Saint-Petersburg

Репутация: 19
Всего: 26



Цитата(Се ля ви @  13.6.2008,  02:16 Найти цитируемый пост)
Насчёт createPrivateState - что значит - у каждого объекта свой

аай, ну это уже опечатка (Copy-Paste'ная) - конечно, я имел в виду объект privateState, а не метод, который его создает.

Цитата(Се ля ви @  13.6.2008,  02:16 Найти цитируемый пост)
Выигрыш будет именно при наличии большого количества методов. 

угу, ну это, действительно, радует =)

Цитата(AKS @  13.6.2008,  06:03 Найти цитируемый пост)
Ну а в общем - мне нравится

Се ля ви, ну а в общем - мне тоже нравится в плане реализации private'ов в стиле Java (как я уже говорил =)). Anyway, хранение всех этих семантически одинаковых геттеров / сеттеров в прототипе, наличие псевдо-инкапсуляции, и отсутствие в каждом методе этих двух строк по загрузке / выгрузке privateState'a, - будет быстрее (замкнутый var всегда будет искаться дольше в цепи, чем this-свойство) и легче (и по ресурсам и по трудозатратам). А вот при какой реализации будет больше трудноуловимых багов, - это надо еще проверить, и, я думаю, вы еще напишете об этом в своей статье =)


Это сообщение отредактировал(а) dsCode - 13.6.2008, 14:21


--------------------
the .code inside
:my music
PM MAIL WWW ICQ Jabber   Вверх
Се ля ви
Дата 16.6.2008, 14:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java/SOAрхитектор
****


Профиль
Группа: Модератор
Сообщений: 2016
Регистрация: 5.6.2004
Где: place without tim e and space

Репутация: 5
Всего: 127



Цитата(AKS @  13.6.2008,  06:47 Найти цитируемый пост)
Вот это: if (arguments[0] != null) не проверка "переданы ли аргументы". Это проверка "нет ли у первого аргумента значений null/undefined". Поэтому и спросил - это дизайн такой на запрет передачи подобных значений или еще что-то.

Да, спасибо за поправку. Изменил на 
Код
if (arguments.length > 0) //...
 

Ещё нововведение - наследование решил снести внутрь объявления класса:
Код
this.constructor.prototype = new E;
 за счёт этого уходит неудобная строка
Код
F.prototype = new E;
, которая мешает  нам... ну в общем, это - в следующей теме smile 

Чуть по-сложнее, но тоже оказалось возможным избавиться и от другой неудобной строчки:
Код
F._class = new F;
 за счёт того, что не обязательно в конструкторе возвращать именно тот объект, который мы создавали в нём. По-умолчанию возвращается this, но можно поставить всё, что угодно. Так что в данном случае мы в конце декларации класса просто ставим 
Код
            this.constructor._class = this;
            return new this.constructor();
, а что бы удалить ненужную ссылку класса на конструктор, в начале объявления объекта приписываем:
Код
            if (this.constructor._class.constructor)
                delete this.constructor._class.constructor;
 - и теперь всё, что связано с созданием объекта, находится внутри конструктора! smile))

Второй заяц, которого мы убиваем этим приёмом - теперь мы создаём класс только в момент создания первого его экземпляра, таким образом в случае, если нам объект не понадобится, мы сэкономим пользователю память.

Ну и некоторые редакторы на "super" ругаются - вроде как зарегистрированное слово, хотя браузеры проглатывают. Не будем искушать судьбу и аргумент функции "createPrivateState" назовём "super_", а то - мало ли что?

В общем, финальный вариант кода:
Код
var E = function() {
        /** @type {function} */ this.constructor = E;
        /** @type {object} */ var _super = this.constructor.prototype;
        //this.constructor.prototype = new this.constructor.prototype.constructor;

        /** @param {Object[]} args */
        this.init = function(args) {
            if (_super.init) _super.init();

            //...

            delete this.init;
            return this;
        }

        //Initialization
        if (arguments.length >= this.constructor.length)
            this.init.apply(this, arguments);

    },
    F = function() {
    
        /** @type {function} */ this.constructor = F;
        
        if (this.constructor._class) {
            
            if (this.constructor._class.constructor)
                delete this.constructor._class.constructor;
            
            //Get privateState object
            this.privateState = this.constructor._class.createPrivateState(this.constructor.prototype);
            this.constructor.prototype = new this.constructor.prototype.constructor;
            
            //Load methods
            for (var m in this.constructor._class)
                if (typeof this.constructor._class[m] == 'function'
                    && m != 'createPrivateState')
                    
                    this[m] = this.constructor._class[m];
            
            //Initialization
            if (arguments.length >= this.constructor.length)
                this.init.apply(this, arguments);
            
        } else {
            
            //Inheritance
            this.constructor.prototype = new E;
            
            var _super,
                _privateField1,
                _privateField2;
            this.createPrivateState = function(super_) {
                return new function() {
                    var _inner = 0,
                        __super = super_,
                        __privateField1,
                        __privateField2;
                    
                    this._get = function() {
                        if (_inner++ == 0) {
                            _super = __super;
                            _privateField1 = __privateField1;
                            _privateField2 = __privateField2;
                        }
                    };
                    
                    this._set = function() {
                        if (_inner-- == 1) {
                            __super = _super;
                            __privateField1 = _privateField1;
                            __privateField2 = _privateField2;
                            
                            _super =
                            _privateField1 =
                            _privateField2 = null;
                        }
                    };
                };
            }
            this.init = function () {
                this.privateState._get();
                
                if (_super.init) _super.init();
                
                //...
                
                delete this.init;
                
                this.privateState._set();
                return this;
            }
            
            this.getPrivateField1 = function() {
                this.privateState._get();
                
                var result = _privateField1;
                
                this.privateState._set();
                return result;
            }
            
            this.setPrivateField1 = function(privateField1) {
                this.privateState._get();
                
                _privateField1 = privateField1;
                
                this.privateState._set();
                return this;
            }
            
            this.constructor._class = this;
            return new this.constructor();
        }
    };


//Тестируем:
var f1 = new F,
    f2 = new F;

alert('f1.setPrivateField1(2).getPrivateField1() = ' + f1.setPrivateField1(2).getPrivateField1());
alert('f2.setPrivateField1(3).getPrivateField1() = ' + f2.setPrivateField1(3).getPrivateField1());
alert('f1.getPrivateField1() = ' + f1.getPrivateField1());

alert('f1.setPrivateField1 === f2.setPrivateField1 = ' + (
    f1.setPrivateField1 === f2.setPrivateField1
));



--------------------
  )
 (
[_])
проф. блог

Кролики думали, что занимаются любовью, а на самом деле их просто разводили...
PM MAIL WWW Skype GTalk   Вверх
Страницы: (4) Все 1 [2] 3 4 
Ответ в темуСоздание новой темы Создание опроса
Форум для вопросов, которые имеются в справочниках, но их поиск вызвал затруднения, или для разработчика требуется совет или просьба отыскать ошибку. Напоминаем: 1) чётко формулируйте вопрос, 2) приведите пример того, что уже сделано, 3) укажите явно, нужен работающий пример или подсказка о том, где найти информацию.
 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | JavaScript: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1139 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.