Хочу абстрактный конструктор
16.09.2012
|
Философ |
Без этой возможности Activator просто вреден, т.к. нет возможности проверить на этапе компиляции существование нужного конструктора. Т.е. выявить ошибку кодирования можно только на этапе выполнения.
16.09.2012 11 комментариев |
Недавно произошёл на эту тему весьма показательный разговор (немного похоже на разговор слепого с глухим, но в принципе пофигу).
Копипаста:
кое-чего мне до сих пор не хватает.
например способа обязать наследников реализовывать нужный мне конструктор.
к сожалению этого нет ни в одном известном мне языке
>Abaddon
фабрики же есть
>>Raziel
Abaddon, задача не просто реализовать конструктор, а исключить ошибки программистов, которые будут этих самых наследников писать
в том числе и свои собственные ошибки тоже исключить
вот поробуй набросать код, решающий эту задачу...
>Abaddon
посредством фиксации конструктора это вряд ли получится
кроме того, жэто может сделать невозможным реализацию требующегося функционала
>>Raziel
как это может?
>Abaddon
это жесть была бы
>>Raziel
покажи
>Abaddon
ну например, есть класс Base::Base(int i), и в наследниках должен быть этот конструктор. А если наследнику требуется дополнительная информация при создании?
>>Raziel
а как её может предоставить обобщённый код, который будет эти самые экземпляры создавать?
вот, допустим, что у нас есть суперХитровыебанная коллекция (кстати, реальная задача)
существующее решение таково:
коллекция держит "контекст", который она передаёт в фабрику
коллекция соответственно обобщённая по типу элементов данных: TEntity, но держит элементы-презентеры (TPresenter), которые и создаёт фабрика
т.е. контекст общий
никакой дополнительной информации ты туда не запихаешь (разве что на уровне статических полей фабрики — но это изврат)
т.е. вполне можно требовать реализацию определённых фабричных методов (или определённых конструкторов).
и новые типы "конструкторов" для этой задачи бесполезны
>>Raziel
а кроме того, обязывание реализации определённых конструторов не накладывает ограничений на дополнительные
>Abaddon
это для этой задачи бесполезны, а так новые параметры в конструктор передаст фабрика
могу даже код привести, где я это применяю
>>Raziel
пока не надо.
там ведь, наверное, большой код, а у меня нет пока желания что-то такое изучать
>Abaddon
[код выпилен]
>>Raziel
я пока не понял твоей основной мысли
>Abaddon
мысль в том, что если бы для ISink был зафиксировать конструктор, реализовать нихрена было бы невозможно
пропадает расширяемость системы
>>Raziel
всё можно было бы реализовать.
в данном случае общего конструктора для наследников просто нет, соотвественно и фиксировать его не нужно.
т.е. никто ведь тебя не обязывает вводить это ограничение.
но сама возможность это сделать была бы полезна
>Abaddon
вот если бы она была, то она бы не дала ничего реализовать
ты ж не знаешь, что понадобиться реализовать в будущем
>>Raziel
нет, Abaddon, ибо когда ты пишешь класс, то либо предполагаешь, что от него можно будет наследоваться (и пишешь его соответственно), либо даёшь возможность накосячить программерам, которые захотят от него наследоваться.
есть ещё третий вариант: объявить класс как sealed
>Abaddon
ну вот как sealed и объявляй, если хочется зафиксировать
смысл ставить какие-то палки в колеса?
ну напишет кто-то класс с конструктором заданного вида, который будет что-то из синглтона подтягивать — тебе от этого легче будет?
>>Raziel
пофигу, ибо экзепляр этого класса по крайней мере можно будет создать (я про такие вещи как Activator)
>Abaddon
и весь этот гемор ради сраного активатора?
нахуй-нахуй
>Abaddon
поставим вопрос так, а что тебе мешает поискать нужный конструктор?
гемор в том, что придется реализовывать бессмысленный конструктор
>>Raziel
я-то пропишу (если не забуду)
а вот посторонний человек, может даже и не знать, что этот конструктор вообще-то необходим
>Abaddon
ну если он необходим, найди его, если нет — кинь исключение
я не вижу проблемы вообще
>>Raziel
исключение — это рантайм
а я хочу такие ошибки перенести в компайл-тайм
именно в этом смысл
>Abaddon
ну так активатор и создает объект в рантайме
т.е. выяснилось, что основная мысль, которую люди не понимают выглядит примерно так:
При использовании активатора(и фабрики тоже) можно напороться на отсутствие нужного конструктора (или фабрики), всё что останется — выбросить исключение, но это рантайм, т.е. ошибка будет в рантайме.
А я хочу такие ошибки перенести в компайл-тайм.
Ф>При использовании активатора(и фабрики тоже) можно напороться на отсутствие нужного конструктора (или фабрики), всё что останется — выбросить исключение, но это рантайм, т.е. ошибка будет в рантайме.
Что касается активатора, то это рефлекшен, там все по определению в рантайме чекается. А насчет фабрики вообще не понял — в каком месте там исключение в рантайме?
AVK>Здравствуйте, Философ, Вы писали:
Ф>>При использовании активатора(и фабрики тоже) можно напороться на отсутствие нужного конструктора (или фабрики), всё что останется — выбросить исключение, но это рантайм, т.е. ошибка будет в рантайме.
AVK>Что касается активатора, то это рефлекшен, там все по определению в рантайме чекается. А насчет фабрики вообще не понял — в каком месте там исключение в рантайме?
Метод получения нужной фабрики может выглядеть например вот так:
т.е. сам бросать исключение, или просто возвращать null.
В последнем случае отсутствие, т.е. в случае null'а, это всё равно исключительная ситуация: не можем мы UI пользователю дать, только сообщение об ошибке показать можем.
Ф>Метод получения нужной фабрики может выглядеть например вот так:
Т.е. специально сделать так, чтобы компилятор не мог проверить? Интересный подход.
AVK>Здравствуйте, Философ, Вы писали:
Ф>>Метод получения нужной фабрики может выглядеть например вот так:
AVK>Т.е. специально сделать так, чтобы компилятор не мог проверить?
А есть другие варианты?
AVK>>Т.е. специально сделать так, чтобы компилятор не мог проверить?
Ф>А есть другие варианты?
Конечно. Про абстрактную фабрику слышал?
AVK>Здравствуйте, Философ, Вы писали:
AVK>>>Т.е. специально сделать так, чтобы компилятор не мог проверить?
Ф>>А есть другие варианты?
AVK>Конечно. Про абстрактную фабрику слышал?
я именно её и привёл.
IUIFactory это и есть абстрактная фабрика.
Если знаешь другой способ, то напишите его здесь — может я заблуждаюсь где-то.
Ф>А есть другие варианты?
Самый простой вариант в дотнете — вместо "фабрики" использовать делегат.
Вот у вас, допустим, класс "коллекция", который хочет создавать новые элементы определённым образом:
В приведённом виде код не работает. Но его легко починить вот так:
Всё. Зачем вам все эти сложности с поиском фабрики по типу?
Просто конструируете NamedArray вот так: