Здравствуйте, vsb, Вы писали:
vsb>Появилась необходимость получить доступ к this перед вызовом super в конструкторе.
Ну, понятно, нельзя. this ещё как бы не существует до вызова super, т.к. не сконструирован и вообще в хз каком состоянии.
Ты пытаешься сделать циклическую зависимость между двумя конструкторами — для конструирования X, нужен Y, а чтобы сконструировать Y нужен X.
Ну... э... не делай так. Надо:
— подумать хорошенько с какого это перепугу renderer вообще должен зависеть от поля которое он рендерит?
— ввести третий класс Z от которого X и Y будут зависеть.
DictAutoCompleteTextField(String id, String dictName, IModel<Dict> model, Zzz zzz) {
super(id, model, Dict.class, new AutoCompleteRenderer(zzz), newAutoCompleteSettings());
this.zzz = zzz;
}
// потом можно и ещё конструктор добавить:
DictAutoCompleteTextField(String id, String dictName, IModel<Dict> model) {
this(id, dictName, model, new Zzz());
}
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, vsb, Вы писали:
vsb>Можно ли придумать какой-нибудь синтаксичекий трюк или что-то в этом роде? Самое логичное для меня это код вроде
vsb>
Здравствуйте, vsb, Вы писали:
vsb>Мне нужно передать в параметр rendered свою реализацию AutoCompleteRenderer, причём vsb>этой реализации нужен доступ к самому наследнику DictAutoCompleteTextField.
Зачем так делать?
vsb>
vsb>Но по какому-то глупому ограничению я не то, что получить доступ к this до вызова super не могу, я вообще ничего там делать не могу.
Что мешает сделать отдельный метод для создания экземпляра. Типа такого:
public static DictAutoCompleteTextField create(...) {
AutoCompleteRenderer renderer = new AutoCompleteRenderer();
DictAutoCompleteTextField result = new DictAutoCompleteTextField(...,renderer);
renderer.setOwner(result);
return result;
}
Re[5]: Получить доступ к this перед вызовом super в конструк
Здравствуйте, vsb, Вы писали:
vsb>·>Не нада. Renderer не должен ничего о локали знать. Он нужен только для обрамления значения T в кусок html. А локализованное значение уже надо держать в самом T. vsb>У меня в T держатся значения для всех (двух) локалей. Простой пример без специфики, по-твоему я не могу держать Integer в качестве T? Ведь чтобы число в строку преобразовать, мне нужна локаль (ну если по уму делать).
Эээ.. Не помню точно как там это всё делается. Вроде локаль-преобразования там делаются через IConverter. Пихать это в тип — по-моему как-то не очень ложится в остальную архитектуру, поэтому у тебя и сабж-проблема. Т.е. "T" уже не должен требовать локали для манипуляций.
Ещё как вариант — не использовать AutoCompleteTextField (уж очень он конкретно заточен под конкретный юзкейз), а написать свой класс компонента, используя AutoCompleteBehavior. Кода там довольно мало.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Получить доступ к this перед вызовом super в конструкторе
Появилась необходимость получить доступ к this перед вызовом super в конструкторе.
Имеется класс AutoCompleteTextField с конструктором
public AutoCompleteTextField(final String id, final IModel<T> model, final Class<T> type,
final IAutoCompleteRenderer<T> renderer, final AutoCompleteSettings settings)
Я создаю наследника этого класса: DictAutoCompleteTextField
Мне нужно передать в параметр rendered свою реализацию AutoCompleteRenderer, причём этой реализации нужен доступ к самому наследнику DictAutoCompleteTextField.
Возможности вызвать что-то вроде AutoCompleteTextFieldюsetRenderer нет, поле AutoCompleteTextFieldюrenderer final и инициализируется в конструкторе. Класс AutoCompleteTextField из фреймворка и менять я его тоже не могу. Функции вроде AutoCompleteTextField.getRenderer тоже нет, чтобы вызвать её и инициализировать мой Renderer после вызова super.
Единственное, что приходит в голову — завести статическую ThreadLocal переменную, присваивать ей AutoCompleteRenderer в его конструкторе и доставать его сразу после вызова super. Какой-то костыль. Ну или reflection-ом достать.
Можно ли придумать какой-нибудь синтаксичекий трюк или что-то в этом роде? Самое логичное для меня это код вроде
Здравствуйте, ·, Вы писали:
·>Здравствуйте, vsb, Вы писали:
vsb>>Появилась необходимость получить доступ к this перед вызовом super в конструкторе. ·>Ну, понятно, нельзя. this ещё как бы не существует до вызова super, т.к. не сконструирован и вообще в хз каком состоянии. ·>Ты пытаешься сделать циклическую зависимость между двумя конструкторами — для конструирования X, нужен Y, а чтобы сконструировать Y нужен X. ·>Ну... э... не делай так. Надо: ·>- подумать хорошенько с какого это перепугу renderer вообще должен зависеть от поля которое он рендерит?
Нада Конкретно — локаль получить, в которой надо выводить. А локаль по уму достаётся из компонента. По-хорошему, конечно, она должна бы передаваться параметром, но не передаётся.
Re[2]: Получить доступ к this перед вызовом super в конструкторе
Здравствуйте, vsb, Вы писали:
vsb>·>- подумать хорошенько с какого это перепугу renderer вообще должен зависеть от поля которое он рендерит?
vsb>Нада Конкретно — локаль получить, в которой надо выводить. А локаль по уму достаётся из компонента. По-хорошему, конечно, она должна бы передаваться параметром, но не передаётся.
Не нада. Renderer не должен ничего о локали знать. Он нужен только для обрамления значения T в кусок html. А локализованное значение уже надо держать в самом T.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[4]: Получить доступ к this перед вызовом super в конструк
Здравствуйте, ·, Вы писали:
vsb>>·>- подумать хорошенько с какого это перепугу renderer вообще должен зависеть от поля которое он рендерит?
vsb>>Нада Конкретно — локаль получить, в которой надо выводить. А локаль по уму достаётся из компонента. По-хорошему, конечно, она должна бы передаваться параметром, но не передаётся. ·>Не нада. Renderer не должен ничего о локали знать. Он нужен только для обрамления значения T в кусок html. А локализованное значение уже надо держать в самом T.
У меня в T держатся значения для всех (двух) локалей. Простой пример без специфики, по-твоему я не могу держать Integer в качестве T? Ведь чтобы число в строку преобразовать, мне нужна локаль (ну если по уму делать).
Здравствуйте, vsb, Вы писали:
vsb>Ну можно и так, но тогда надо для каждого наследника что-то подобное писать, да и общий стиль нарушается, все компоненты через new создаются.
Сделайте фабрику
Re[3]: Получить доступ к this перед вызовом super в конструктор
Здравствуйте, vsb, Вы писали:
vsb>Здравствуйте, ·, Вы писали:
vsb>Нада Конкретно — локаль получить, в которой надо выводить. А локаль по уму достаётся из компонента. По-хорошему, конечно, она должна бы передаваться параметром, но не передаётся.
У каждого компонента своя локаль ?
Re: Получить доступ к this перед вызовом super в конструкторе
Здравствуйте, vsb, Вы писали:
vsb>Но по какому-то глупому ограничению я не то, что получить доступ к this до вызова super не могу, я вообще ничего там делать не могу.
Оно совсем не глупое. До вызова super не отработал конструктор базового класса. Если , например, поля производного класса определяются в конструкторе через поля базового, то нетрудно себе представить, чем это может закончиться.
Запрет на доступ к this на первый взгляд менее логичен, так как this — это ссылка на объект и она изменена быть не может внутри вызова super(). Так что взять ее вроде как безопасно, и я пока не вижу, к каким проблемам это могло бы привести. Но что ты сможешь сделать, взяв ее ? Присваивать ее полям нельзя — еще не сконструированы поля базового класса, так что см. выше. Передать параметру конструктора ? Чем это будет лучше, чем если сделать это после вызова super ? Завести локальную переменную, как в твоем гипотетическом примере внизу ? Это такой ящик Пандоры открыть, что мало никому не покажется. Кто мне в таком случае запретит передать в new AutoCompleteRenderer() какое-то поле базового класса ?
With best regards
Pavel Dvorkin
Re[4]: Получить доступ к this перед вызовом super в конструктор
Здравствуйте, stenkil, Вы писали:
vsb>>Нада Конкретно — локаль получить, в которой надо выводить. А локаль по уму достаётся из компонента. По-хорошему, конечно, она должна бы передаваться параметром, но не передаётся.
S>У каждого компонента своя локаль ?
Теоретически да. Дефолтная реализация берёт локаль из сессии пользователя, но ничего не мешает её изменить. Уж не знаю, зачем это понадобилось.
Re[2]: Получить доступ к this перед вызовом super в конструкторе
Здравствуйте, Pavel Dvorkin, Вы писали:
vsb>>Но по какому-то глупому ограничению я не то, что получить доступ к this до вызова super не могу, я вообще ничего там делать не могу.
PD>Оно совсем не глупое. До вызова super не отработал конструктор базового класса. Если , например, поля производного класса определяются в конструкторе через поля базового, то нетрудно себе представить, чем это может закончиться.
Хз, не вижу проблемы. До вызова конструктора базового класса поля содержат нулевые значения, после вызова конструктора отрабатывают инициализаторы, если они есть. Ну и да, в данном случае мне this нужен просто как указатель, а не делать что-то с ним. Причём по факту так и есть, можно в конструкторе базового класса прокастовать this до производного класса и спокойно делать что угодно и ничего не бахнет.
На самом деле самое глупое то, что я вообще не могу никакой код написать до вызова super, пусть он даже к объекту класса пока не имеет никакого отношения. Вот этому объяснения я не вижу и не удивлюсь, если в байткоде такого ограничения нет. Тем более, что по факту любое выражение, переданное параметром в super, таки вычисляется до вызова super.
PD>Запрет на доступ к this на первый взгляд менее логичен, так как this — это ссылка на объект и она изменена быть не может внутри вызова super(). Так что взять ее вроде как безопасно, и я пока не вижу, к каким проблемам это могло бы привести. Но что ты сможешь сделать, взяв ее ? Присваивать ее полям нельзя — еще не сконструированы поля базового класса, так что см. выше.
Я могу передать this в new AutoCompleteRenderer(). Ну или просто сделать AutoCompleteRenderer не статическим вложенным классом, передав его неявно. Никаких проблем это вызвать не может, т.к. я его в конструкторе использовать не буду. Ну теоретически понятно, что мог бы, и увидел бы инициализированный нулями объект, плохо-плохо, понимаю.
PD>Передать параметру конструктора ? Чем это будет лучше, чем если сделать это после вызова super ? Завести локальную переменную, как в твоем гипотетическом примере внизу ? Это такой ящик Пандоры открыть, что мало никому не покажется. Кто мне в таком случае запретит передать в new AutoCompleteRenderer() какое-то поле базового класса ?
Ну я говорю, если уж так не хочется связываться с this, пускай там будет любой код, не трогающий this. Те же AutoCompleteSettings я вынужден зачем-то выносить в отдельный статический метод, хотя мог бы написать по-человечески.
Re[3]: Получить доступ к this перед вызовом super в конструкторе
Здравствуйте, vsb, Вы писали:
vsb>Я могу передать this в new AutoCompleteRenderer(). Ну или просто сделать AutoCompleteRenderer не статическим вложенным классом, передав его неявно. Никаких проблем это вызвать не может, т.к. я его в конструкторе использовать не буду. Ну теоретически понятно, что мог бы, и увидел бы инициализированный нулями объект, плохо-плохо, понимаю.
Вот именно. Передан был бы недоконструированный объект с нулевыми полями, и бог знает, что ты с этими полями будешь в new AutoCompleteRenderer делать.Да, передал бы ты туда только this, но дай тебе этот this — и ты там все , что в нем, получишь.
PD>>Передать параметру конструктора ? Чем это будет лучше, чем если сделать это после вызова super ? Завести локальную переменную, как в твоем гипотетическом примере внизу ? Это такой ящик Пандоры открыть, что мало никому не покажется. Кто мне в таком случае запретит передать в new AutoCompleteRenderer() какое-то поле базового класса ?
vsb>Ну я говорю, если уж так не хочется связываться с this, пускай там будет любой код, не трогающий this.
Не трогают this только локальные переменные и формальные параметры (ну и static, конечно). Вот int x = 10; написать там и впрямь было бы можно, и вполне безопасно. А все остальное так или иначе трогает this, в том числе и вложенный нестатический класс. Но было бы странным дать разрешение на введение до super кода, который не может обращаться к полям класса.
With best regards
Pavel Dvorkin
Re[4]: Получить доступ к this перед вызовом super в конструк
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Но было бы странным дать разрешение на введение до super кода, который не может обращаться к полям класса.
И что же в этом странного? Это прекрасно решило бы мою проблему. Даже две проблемы. Вторая не такая существенная, но тоже неприятная. Видно её по названию newAutoCompleteSettings() под которым скрывается код инициализации настроек.
я написать не могу, вынужден городить неуместный статический метод. Ну ладно, это, как я уже написал, проблема несущественная, хотя я бы предпочёл писать всю логику инициализации в одном месте.
Причём компилятор вполне умеет отделять такой код. Нельзя написать super(this.field), т.к. идёт обращение к this до вызова super.
В таком виде я проблем не вижу, но при условии, что созданный локальный объект используется только для передачи в super. При этом я не утверждаю, что проблемы нет, может, я просто ее не увидел.
Обосновать такое разрешение, похоже, можно (собственно, мы тут этим и занимались), но причины, по которым локальную переменную использовать можно, а к полям обратиться нельзя, не вполне очевидны, а поэтому введение такого разрешения/запрета делает язык менее ясным. Проще запретить все.
With best regards
Pavel Dvorkin
Re[3]: Получить доступ к this перед вызовом super в конструкторе
Здравствуйте, vsb, Вы писали:
PD>>Оно совсем не глупое. До вызова super не отработал конструктор базового класса. Если , например, поля производного класса определяются в конструкторе через поля базового, то нетрудно себе представить, чем это может закончиться.
vsb>Хз, не вижу проблемы. До вызова конструктора базового класса поля содержат нулевые значения, после вызова конструктора отрабатывают инициализаторы, если они есть. Ну и да, в данном случае мне this нужен просто как указатель, а не делать что-то с ним. Причём по факту так и есть, можно в конструкторе базового класса прокастовать this до производного класса и спокойно делать что угодно и ничего не бахнет.
По теме ссылку увидел. Про конструкторы и их проблемы: