feat: introduce HasComponentsOfType for typed child containers#24186
feat: introduce HasComponentsOfType for typed child containers#24186
Conversation
Adds HasComponentsOfType<T extends Component> as the typed counterpart of HasComponents, for containers that should only accept a specific child component type (e.g. a breadcrumb trail that only accepts breadcrumb items). HasComponents now extends HasComponentsOfType<Component> and keeps the untyped add(String) convenience. All existing default methods are preserved via inheritance.
The childFactory-null error message now references HasComponentsOfType since that is where the bindChildren default method lives.
|
There is one compatibility concern with widening the Collection parameters: Third-party code that does: class MyLayout extends Component implements HasComponents {
@Override
public void add(Collection<Component> components) { ... } // today's signature
} will fail to compile against the new API. Java's override rules require the generic signature to match, not just the erasure. Because Collection and Collection<? extends Component> have the same erasure but different generic signatures, the subclass gets a "method does not override" error AND a "same erasure, different signatures" clash. It sounds like a rare case but it's not 100% compatible |
…ds T Follows PECS — the Collections passed to add/remove and the factory passed to bindChildren are producers of T, so wildcards let callers pass e.g. a List<SubItem> or a factory returning SubItem when the container type is Item. Binary compatible (same erasure); source-level this is a breaking change for third-party overrides that pinned the parameter to Collection<Component> or SerializableFunction<..., Component>, which must be updated to match the widened signatures.
Good point. Know that you mentioned it, I remember a similar thing was discussed on another pr recently, but I don't recall the conclusion and what pr was. I'll try to find it on Monday |
|
Probably it was exactly those methods, discussed in an issue. And IIRC the conclusion was that it could be a breaking change for add-ons |
|
It seems it's postponed to Vaadin 26. Better revert. Sorry for the inconvenience |
… ? extends T" This reverts commit 27e45a4.
There was a problem hiding this comment.
The idea looks good to me, though the new API is not fully typed - we hesitate to do full changes because of their breaking nature, thus, we may want to make a second round in Vaadin 26 to close this gap.
We perhaps don't have to immediately apply this interface to our standard components like Tabs, Accordion, and others, where the inner components are always typed, but that's something to consider in the future.
Finally, I can confirm that this change is compatible with the Flow components code base and doesn't trigger compilation errors, but I admit a small risk of unpredicted breaking changes anyway. I believe we can merge this right now, but keep an eye on this topic during alpha and beta testing.
|



Adds HasComponentsOfType as the typed counterpart of HasComponents, for containers that should only accept a specific child component type (e.g. a breadcrumb trail that only accepts breadcrumb items). HasComponents now extends HasComponentsOfType and keeps the untyped add(String) convenience. All existing default methods are preserved via inheritance.