On Tue, Mar 8, 2011 at 11:22 PM, Maarten Billemont <[email protected]> wrote:
>>>>
>>>> Just like EJBs, you should be careful about how much interaction you do
>>>> beyond your object's scope within the constructor. Your component doesn't
>>>> have a hierarchy, getPage() cannot be accessed, none of your subclass
>>>> constructors have been invoked and therefore your instance is not properly
>>>> initialized and ready for use.
>>> not really sure what you mean by subclass constructors or how they
>>> come into play when constructing an instance...
>> If I understand correctly, here is an example of what he means :
>
>
> Exactly. If B extends A and I do something in A's constructor that goes
> beyond the scope of setting up A's instance variables, then I risk a
> side-effect that relies on the instance to be constructed at B's level as
> well. There's nothing in the JVM that prevents this and these bugs are very
> hard to see and debug. They should be avoided by good coding practices.
yep, calling overridable methods from constructors is bad - you just
made the case for making page.oninitialize() final...
>
> On 08 Mar 2011, at 22:07, Igor Vaynberg wrote:
>>
>> i think code like this should be possible:
>>
>> NameEditor e=new NameEditor("name", firstNameModel, lastNameModel);
>> e.getFirstNameEditor().setRequired(true);
>> e.getLastNameEditor().setEnabled(false);
>
>> taking the previous example of a name editor, with constructor we have:
>>
>> class nameeditor extends panel {
>> public nameeditor(...) {
>> add(new textfield("first",..);
>> add(new textifled("last", ...);
>> }
>> public textfield getfirst() { return get("first"); }
>> public textfield getlast() { return get("last"); }
>> }
>
> Firstly, it's my opinion that you really shouldn't be doing anything to
> components directly, especially not from outside your class. As for why, see
> Encapsulation and Law of Demeter.
neither of the two apply because nameeditor explicitly exposes the two
components as part of its contract via public getters.
> But if you really wanted to use this pattern, it really wouldn't have to be
> as cumbersome as you make it out to be. Also, I really don't like condoning
> get(String), it's nasty and very type-unfriendly. It also breaks as soon as
> you do any refactoring in your component hierarchy.
yes, i traded off some refactorability for better memory footprint.
imho a perfectly valid trade off when memory and space are costly.
> class NameEditor extends Panel {
> TextField<String> firstField;
> TextField<String> lastField;
> @Override protected void onInitialize() { super.onInitialize();
> add(getFirst(), getLast()); }
> public textfield getFirst() { if (firstField == null) firstField = new
> TextField<String>(); return firstField; }
> public textfield getLast() { if (lastField == null) lastField = new
> TextField<String>(); return lastField; }
> }
there are still problems with this:
*you still have the two extra memory slots that are a complete waste
here - component references
*the lazy init code is cumbersome to write
*you are missing the two slots needed to pass models from constructor
to the two textfields - so thats four extra slots total that you have
now forced on users
* the components i get from the getters are not added to their parent
- for more complex components that need access to their markup this is
a problem, eg if
("text".equals(getFirst().getMarkupTag().get("type")).......not
necessarily a good example taking this particular custom component as
context, but a valid usecase in plenty of other situations.
-igor
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]