Просмотр полной версии : Почему нельзя приватный конструктор?
orcpochta
25.02.2010, 02:46
Как быть, например, с такой ситуацией, что экземпляр класса должен создаваться только если параметры, передаваемые в конструктор, удовлетворяют некоторому набору условий?
Т.е. есть статический метод класса, проверяющий входные параметры, и если они верны, передает эти параметры в конструктор и возвращает созданный экземпляр, если же параметры не удовлетворяют требованиям - возвращается null.
var instance:SomeClass = SomeClass.createInstance(... args);
т.е. запрещаем напрямую создавать экземпляр
(var instance:SomeClass = new SomeClass(... args))
Опять же, паттерн Singleton примерно на этом же основан - как быть с ним?
Паттерн синглтон применительно к AS3 не имеет смысла. А что мешает в самом конструкторе проверить?
orcpochta
25.02.2010, 02:59
Паттерн синглтон применительно к AS3 не имеет смысла.
:
Обоснуйте. Что мешает мне хотеть иметь в AS3 один-единственный экземпляр моего класса?
А что мешает в самом конструкторе проверить?
Мешает то, что независимо от результата проверки будет создан объект этого класса, пусть и "покалеченный". Или нет? Конструктор можно прерывать и он вернет null вместо объекта? В Муке вроде такого не было - сейчас проверю)))
UPD: не вышло
UPD2: ну, предположим, Singleton я догадался как реализовать с извращениями и некоторыми ограничениями, а как быть с тем, что не должен создаваться экземпляр класса, если входные условия не являются допустимыми?
Синглтон имеет смысл когда вы не можете заранее определить когда будет создан объект - такая ситуация возможна только если у вас код выполняется в несколько потоков, что, вобщем-то не возможно в AS3. Если выбросить ошибку, то, на сколько я понимаю, объект не создасться.
EDIT: На самом деле, я конечно немного погарячился, и в AS3 есть аж целых 3 синглтона: null, undefined и NativeApplication (последний - не понятно почему). Но вам, как разработчику использующему язык, а не разрабатывающему язык от синглтона только вред :)
Сделайте в конструкторе обязательный аргумент такого типа, который недоступен никому, кроме этому вашему классу (т.е. тот вспомогательный класс, который определяется в том же файле). Таким образом создать экземляр через new будет нельзя, а в вашем статическом методе устраивайте какие хотите проверки.. пойдёт?
wvxvw, ну чего ты своим академизмом людей мучаешь?=) ему вроде ехать, а не шашечки надоть
orcpochta
25.02.2010, 03:36
Синглтон имеет смысл когда вы не можете заранее определить когда будет создан объект - такая ситуация возможна только если у вас код выполняется в несколько потоков, что, вобщем-то не возможно в AS3.
Ситуаций может быть много. Самая тривиальная из них - это когда пишешь библиотеку для кого-то (или просто команда работает над большим проектом) и надо быть уверенным, что экземпляр именно этого класса будет создан один-единственный, чтобы там не пытались сотворить человеки, юзающие эту библиотеку.
Если выбросить ошибку, то, на сколько я понимаю, объект не создасться.
Круто! Спасибо! Причем именно null возвращается - то, что нужно!)))
Добавлено через 11 минут
Сделайте в конструкторе обязательный аргумент такого типа, который недоступен никому, кроме этому вашему классу (т.е. тот вспомогательный класс, который определяется в том же файле). Таким образом создать экземляр через new будет нельзя, а в вашем статическом методе устраивайте какие хотите проверки.. пойдёт?
Разжуйте, пожалуйста))) Не пойму, что за тип, недоступный никому, кроме моего класса и который определяется в том же файле. 10 минут втыкал и отчаялся понять - объясните, плиз)))
http://www.darronschall.com/weblog/2007/11/actionscript-3-singleton-redux.cfm
wvxvw, ну чего ты своим академизмом людей мучаешь?=) ему вроде ехать, а не шашечки надоть
по-моему писать синглтон - это просто лишний труд. А если человек создал лишний объект нужного типа, то никто ему не помешает это же сделать как бы вы ни пытались это предотвратить - он просто возьмет и отредактирует ваш код. При этом, возможно, будет прав - а вы ему только палки в колеса ставите.
Ну... синглтоны штука интересная.
Почему бы мне не воспользоваться синглтоном если у меня в приложении может быть только один экземпляр данного класса? Хотя в принципе допускаю для таких целей использование статического класса.
orcpochta
04.03.2010, 11:30
Хм... столкнулся в итоге с тем, что если сделать методом, предложенным fljot-мо, то класс невозможно будет расширить, да?
ну вот отсюда например можно слизать
............................
public class Controller implements IController {
protected const SINGLETON_MSG : String = "Controller Singleton already constructed!";
protected var view : IView;
protected var commandMap : Array;
protected static var instance : IController;
public function Controller( ) {
if (instance != null) throw Error(SINGLETON_MSG);
instance = this;
commandMap = new Array();
initializeController();
}
............................
(с) pureMVC
orcpochta
04.03.2010, 15:13
Elser, если это в тему синглтона, то это не синглтон - с помощью такого подхода можно наплодить тьму нулевых объектов [тут нагнал]и все они будут класса Controller[/тут нагнал])))
с помощью такого подхода можно наплодить
о чем вам говорит protected static ?
здесь подразумевается Controller.instance - свойство самого класса а не его экземпляров
orcpochta
04.03.2010, 15:52
о чем вам говорит protected static ?
здесь подразумевается Controller.instance - свойство самого класса а не его экземпляров
а причем тут вообще protected и static? я говорил про этот случай:
var asd:Controller = new Controller( );
try
{
var qwe:Controller = new Controller( );
}
catch (e:Error)
{
}
trace(qwe)
будет создан qwe, но единственное я нагнал, что он будет класса Controller.
Но все-равно, как мне кажется, плохой способ, т.к. потом придется делать проверку, нуль это или не нуль, опять же выдается нуль, там, где должна выдаваться ссылка на уже существующий объект - короче, красота и простота синглтона теряется.
static - свойство класса - для всех инстансов ВСЕГДА одинаковое значение
protected - и это касается также всех потомков!
var asd:Controller = new Controller( );
try
{
var qwe:Controller = new Controller( );// порождение переменной qwe не будет выполнено
}
catch (e:Error)
{
trace(e.message);// Controller Singleton already constructed!
}
trace(qwe); //null - нет такой переменной (а не переменная равная null как Вы решили)
var tst:Object = qwe; // error 1120 Access of undefined property qwe
orcpochta, не вводите людей в заблуждения
orcpochta
07.03.2010, 01:56
static - свойство класса - для всех инстансов ВСЕГДА одинаковое значение
protected - и это касается также всех потомков!
orcpochta, не вводите людей в заблуждения
Что вы пытаетесь мне объяснить? Я уже сказал вам, что static и protected не имеет отношения к обсуждаемой теме. Я рад, что вы понимаете значения этих модификаторов, но еще раз вам повторю, что приведенный вами пример - это не синглтон (в том ключе, в каком поднималась тема), и я привел вам пример, что можно создать другой объект (нулевой объект qwe) там, где должна возвращаться ссылка на уже существующий объект.
Вы конечно можете сослаться на то, что у нас разные понимания синглтонов - и будете наверно по своему правы, но опять же модификаторы static и protected не будут иметь к этому никакого отношения....)))
кстати
trace(qwe); //null - нет такой переменной (а не переменная равная null как Вы решили)
var tst:Object = qwe; // error 1120 Access of undefined property qwe
вы гоните))))
Ну... синглтоны штука интересная.
Почему бы мне не воспользоваться синглтоном если у меня в приложении может быть только один экземпляр данного класса? Хотя в принципе допускаю для таких целей использование статического класса.
Рассуждения надо начинать с "а почему бы воспользоваться", а не "почему бы и нет" :) Так можно много чего в приложение вписать - если есть время и творческий настрой - то, вобщем, конечно, отчего бы и нет? :)
(с) pureMVC
Тысячи [...] не могут ошибаться!
PureMVC - порождение злого гения из лепрозория. Другими словами - обычный марамз - результат большого ума и еще большего желания его куда-то применить.
Единственный смысл его использовать в AS3 - это если вам за код платят познаково, да и то, можно просто выдумывать названия переменных подлиннее - меньше работы за те же деньги (т.как автокомплит будет большую часть работы делать).
Синглтон имеет смысл когда вы не можете заранее определить когда будет создан объект - такая ситуация возможна только если у вас код выполняется в несколько потоков, что, вобщем-то не возможно в AS3.
Да во FlexFramework в какой менеджер не плюнь - статический класс, использующий синглтон
Соглашусь, что синглтоны и статические классы иже с ними (сингтоны хоть наследовать и передавать в качестве параметров можно) - зло, т.к. создают глобальную точку доступа, чем повышают сцепленность между классами.
Но:
1. В каждом проекте есть много ситуаций когда лучше воспользоваться ими, чем протаскивать кучу параметров в недра своей архитектуры.
2. Приватный конструктор может потребоваться для других целей:
- классы, которые нет смысла инстанцировать;
- запрет на прямое создание объекта - чтобы из пула через статический метод доставали
3. Объекты без состояния можно сделать синглтонами - это не увеличит сцепленность, но съэкономит ресурсы на пересоздание, это даже не синглтоны уже а "приспособленцы"
И совсем не понятно почему "они" запретили "private" в конструкторе то?
А зачем запрещать в коде-то? Напишите в коментариях - ваши запреты в коде не будут работать никогда, потому что от этих запретов начинает пухнуть голова, после чего просто приходится править чужой код и удалять все это от туда. Код это ж для того, чтобы работало, а не для того, чтобы максимально усложнить жизнь окружающим...
Аналогичная ситуация: mx.controls.Tree - уже второй день пытаюсь заставить показать DragManager.MOVE фидбек при перетаскивании на него объектов из другого компонента. А все потому что кто-то, опять же от большого ума, решил это запретить.
Еще раз, нет смысла в синглетоне в AS3 - ну вот просто нет, и все...
немножко уеду вверх своим коментом.
protected static - абсурд.
статичные методы\перменные и т.д. и т.п. не наследуются, пора бы уже подумать головой.
Не скажите, wvxvw, ошибка компиляции доходчивее коментария, да и зачем держать все в голове - "этот класс можно инштацировать или нельзя? - э... надо полезть посмотреть..."
Отсылка эксепшенов - тоже не плохо, но одно дело ошибка компиляции, а другое рантайм - вон во ФлешДевелопе до сих пор дебагера нет - он тебе даже на клас не ткнет - придется самому файл класса открывать, читая стек вызовов эксепшена.
Но тут видимо у всех свой подход, и я врядли вас и кого-быто нибыло переспорю.
protected static - абсурд.
Ан нет! Это делает возможным ссылатьcя на это поле в наследнике этого класса:
class A
{
protected static field:Int = 10;
}
class B extends A
{
public function execute()
{
trace(A.field);
}
}
(new B()).execute();
по поводу приватного конструктора.
синглтоны на самом деле вещь достаточно унылая применительно к as3.
во первых вам необходимо "накалякать" код класса который будет у вас синглтоном, сделать его интерналом и наваять следом враппер какой-нибудь где в конструкторе будет просто вываливаться ошибка о том что нельзя создавать такой объект.
throw new Error("ай-йай йай, по попе ремнем тебе");
в getInstance() уже инициализироть internal класс.
мой вам совет - не стоит морочиться.
protected static - абсурд.
Не правда. У меня в суперклассе есть константа статическая (я не хочу их размножать), и я хочу ее же использовать в любом наследнике этого класса - что мне тогда делать?
хорошо ошибся - я про методы, про наследуемость я имел в виду что их нельзя заоверрайдить.
не уловил я сути комментов, поэтому "обознался". не совсем понимаю к чему вся дискуссия, все уже сказано вроде.
Не скажите, wvxvw, ошибка компиляции доходчивее коментария, да и зачем держать все в голове - "этот класс можно инштацировать или нельзя? - э... надо полезть посмотреть..."
[/AS3]
Да, конечно, лучше нагреть ЦПЮ пользователю, пусть подумает лишний раз - а мне-то зачем думать? :)
protected static - абсурд.
Да-да, а мы вот как-то предпочитаем «для своих» статики оставлять, а остальным фигу. private static тоже встречается.
orcpochta
20.04.2010, 15:15
Придумал элегантное решение, как залочить конструктор от использования извне напрямую, т.е. получил аналог приватного конструктора, доступного только из статического метода класса. Отличается от способа, предложенного fljot тем, что не использует вспомогательный класс, определенный в том же файле (ну не нравится мне такая структура, что в одном файле определяется два класса - ничего не могу с собой поделать :) )
Ну и самый главный и категорический плюс - это то, что не возникнет проблем с наследованием такого класса - все гибко и четко)))
package
{
public class MyClass
{
//получаем экземпляр нашего класса через публичный статический метод
public static function newMyClass ("список аргументов"):MyClass
{
if ("проверяем список аргументов на валидность")
{
//если все ОК, вызываем приватный статический метод-локер конструктора
return MyClass.constructorLocker("список аргументов");
}
throw new Error("аргументы не прошли тест на валидность");
//или же возвращаем экземпляр с дефолтными параметрами
}
//статический приватный метод-локер конструктора
private static function constructorLocker ("список аргументов"):MyClass
{
return new MyClass("список аргументов", arguments.callee);
//обратите внимание, что к списку аргументов добавилась ссылка на текущий метод-локер
}
//конструктор класса
public function MyClass ("список аргументов", caller:Function)
{
//делаем проверку, что конструктор был вызван именно из метода-локера,
//а значит из статического метода, предназначенного для создания нового экземпляра
if (caller != MyClass.constructorLocker)
{
throw new Error("Constructor access error!");
}
//если наш класс расширяет другой класс, то эту проверку надо сделать
//сразу после super("список аргументов") - единственное на мой взгляд
//слабое место, т.к. конструктор супер класса все равно выполняется,
//но ничего не поделаешь - нельзя использовать throw перед super.
}
}
}
Обратите внимание, что не используется arguments.caller в конструкторе для проверки (хотя с помощью него можно было бы избежать введения последнего аргумента caller:Function в объявление конструктора) - это связано с тем, что arguments.caller стал анахронизмом (или в AS3 он всегда им был? :) ) :
http://help.adobe.com/ru_RU/AS3LCR/Flex_4.0/arguments.html
Ну и если надо расширить наш класс, то я теперь не вижу особых проблем для этого - хотя они наверняка есть для такого исполнения, но мне кажется их можно будет обойти)))
Может мне свой блог завести, куда бы я складывал свой бред и не мешал всему форуму? :D
Psycho Tiger
20.04.2010, 16:07
Тяга к красивому это хорошо. Хотя тут проблема решается 2 строчками.
var myClass:MyClass=new MyClass();
if (!myClass.valid) myClass=null;
Паттернить ради паттернства это глупо.
orcpochta
20.04.2010, 16:18
Тяга к красивому это хорошо. Хотя тут проблема решается 2 строчками.
var myClass:MyClass=new MyClass();
if (!myClass.valid) myClass=null;
Паттернить ради паттернства это глупо.
вот в таких мелочах большие проекты и сыпятся)))
я исхожу из того, что если "что-то" нельзя, то не надо давать это "что-то" делать, а не надеяться, что тот, кто это "что-то" пытается делать, проявит благоразумность)))
Отчего не сделать так? Все просто и понятно, без перегиба:
package
{
public class MyClass
{
static protected var _numOfInstances:uint = 0;
//получаем экземпляр нашего класса через публичный статический метод
static public function newMyClass( "список аргументов" ):MyClass
{
if( !(_numOfInstances == 0 && "проверяем список аргументов на валидность") )
{
throw new Error( "Экзепляр был уже создан или аргументы не прошли тест на валидность" );
return null;
}
//если все ОК, вызываем конструктор
return new MyClass( "список аргументов" );
}
//конструктор класса
public function MyClass( "список аргументов" )
{
// делаем проверку сколько экземпляров было сделано
if( _numOfInstances > 0 )
{
throw new Error("Constructor access error!");
return;
}
++_numOfInstances;
// А тут все гуд. Инициализация
}
}
}
orcpochta
20.04.2010, 21:55
Отчего не сделать так? Все просто и понятно, без перегиба:
у вас тут "смешались в кучу кони, люди"... :)
Psycho Tiger
20.04.2010, 22:12
А, проект большой? Ок, тогда там должна быть хорошая и вменяемая архитектура. Если что то создаётся так, как создаваться не должно - должен быть RTE без факта продолжения, во всяком случае во время дебага. Вы же хотите "делать много чего, а если что то не хорошо - то null". Окей, зачем вам null? Что вы хотите с null сделать? Проверить, а всё ли было хорошо, сравнив объект с null`ом? Дак флаг-геттер класса тоже отлично справится с этим.
В принципе, я даже могу представить себе ситуацию когда создавать объект, который при стечении обстоятельств должен вернуть null, вместо ссылки на себя без вызова RTE. Только с точки зрения процессора пользователя куда дешевле проверить все данные ДО того, как создавать новый экземпляр класса.
orcpochta
20.04.2010, 22:19
Почему же null? null - это если кэтчить выброшенную ошибку, а так сразу прерывание - что, собственно, очень даже хорошо.
у вас тут "смешались в кучу кони, люди"...
А где именно смешались?
Psycho Tiger, насколько я понял, человеку нужно было создать один единственный экземпляр класса, в прямом смысле. Т.е неприемлимо было создавать еще экзепляры и спрашивать их valid или не valid. Поэтому и null, так как экземпляр может быть только один.
У вас тут собственно тот же null.. А что вы с ним собираетесь потом делать? Разницы то никакой.
var myClass:MyClass=new MyClass();
if (!myClass.valid) myClass=null;
orcpochta
20.04.2010, 22:23
А где именно смешались?
Psycho Tiger, насколько я понял, человеку нужно было создать один единственный экземпляр класса, в прямом смысле. Т.е неприемлимо было создавать еще экзепляры и спрашивать их valid или не valid. Поэтому и null, так как экземпляр может быть только один.
вы не правильно поняли)))
первоначально вопрос стоял, как вернуть приватный конструктор, а паттерн синглтон был лишь приведен в пример полезности приватного конструктора.
т.е. синглтон - это уже даже не задача, если имеем подобие приватного конструктора, а вытекающее из оного
у вас же нет никакого приватного конструктора
в общем забудьте про синглтон, я не знаю, зачем вы к нему сейчас прицепились))))
Прошу прощения, не так все понял. Думал именно про синглтон в конце темы страсти пошли ))
Psycho Tiger
20.04.2010, 22:46
если же параметры не удовлетворяют требованиям - возвращается null.
Почему же null? null - это если кэтчить выброшенную ошибку, а так сразу прерывание - что, собственно, очень даже хорошо.
Я говорил в контексте сформулированной задачи. А какой у вас контекст?
orcpochta
21.04.2010, 00:15
ну это же было как пример, вопрос-то стоял про приватный конструктор, а не про возвращение null)))
что-то мы о разных вещах как-будто говорим)))
Добавлено через 23 часа 16 минут
Привел мысли в порядок - все стало еще лучше и проще:
//класс с залоченным конструктором
package
{
public class LockedClass
{
public static function newLockedClassObject ( ):LockedClass
{
return new LockedClass(LockedClass.key);
}
//собственно ключ
//private - делаем класс ненаследуемым
//protected - разрешаем наследовать этот класс
protected static function key ( ):void { }
public function LockedClass (key:Function)
{
if (key != LockedClass.key) throw new Error("Constructor access error!");
}
}
}
//класс, расширяющий залоченный класс
package
{
public class LockedExtend extends LockedClass
{
public static function newLockedExtendObject ( ):LockedExtend
{
return new LockedExtend(LockedClass.key);
}
public function LockedExtend (key:Function)
{
super(key);
}
}
}
все отлично и на мой взгляд придраться не к чему.
А что касается варианта fljot-а, где использовался вспомогательный локер-класс, объявленный в том же файле, что и класс, которому мы закрывали конструктор, то:
- этот класс невозможно было наследовать
- если в файле внешнего класса (того, который собирается использовать класс с залоченным конструктором) объявить класс с таким же именем как и у локер-класса и потом передать его в конструктор залоченного класса, то флешка скомпилируется, но какие процессы там будут происходить - я не берусь предполагать (у меня был просто белый экран). Один факт того, что можно в результате таких действий получить непредвиденный результат - уже Epic Fail...)))
- Назовите Самый Обсуждаемый паттерн?
- Хе. Синглетон!
- А почему?
- А потому что остальные слишком сложные.
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.