Hi,
for extending tapestrys internal service classes it's often required to
copy a lot of code because almost everything is private. Why not
changing it to protected to allow others to extend those classes?

Because it makes keeping backward-compatibility way harder and that's very important for the project.
Protected methods are normally not part of the official stable api. So there's no difference for maintaining backward compatibility. I don't see any drawback here

Not to mention that protected fields are something to be avoided in OOP.
That's true for fields in some cases, right. But IMO does not apply to most methods. Especially in service classes where certain functionality is moved to methods - here one of the most powerful oop concepts is to override those methods to change behaviour. Of course the most advanced way would be to have an abstract basic implementation of each service plus implementions of each aspect of that service. But that would be much overhead in most cases.

In addition, you can use advise or overriding for dealing with most problems.
Sure, one can use advice to achieve basically the same. But this will cause much more problems: - same backward compatibility issue as if you would override internal methods - but you would not get a compiler message about this. Instead the behaviour would silently fall back to the default. Bad thing!
- Much more (and much less readable) complex code for trivial changes.

Overriding is only a solution if you have a drop-in replacement for a service. That means in most cases that you have to copy a service and to a change there.


Another similar problem are final methods. Last week we created a few custom form field components and we started with extending AbstractField which contains most required stuff. All was fine until we wanted to change the label behaviour:
- if a "label" parameter is bound, use this
- otherwise check a custom service
- otherwise check the bound parameter for a label annotation
- otherwise use defaultLabelProvider

But... defaultLabel() is package protected + final. So we cannot:
- override the method
- test if the parameter is bound (bound is always true when a defaultParam() method exists)

So I had to copy the whole AbstractField component to do the simple change. Alternatively I'd have to change/decorate ComponentDefaultProvider but this would change the behaviour in all components, not just those special ones.

So how should one solve such problems if so many methods are private (or package protected) and/or final?

Kind regards,
Michael.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tapestry.apache.org
For additional commands, e-mail: dev-h...@tapestry.apache.org

Reply via email to