On maandag 10 april 2017 23:48:27 CEST Pedro Santos wrote:
> Hi Emond,
> 
> > Your proposal will not work because Java does not resolve functional
> > interfaces to subtypes of the target type. For example, take the Label
> > constructor:
> I know, and that is just a good thing. Take TextField for example, we don't
> want it constructed with a function as a model:
> 
> new TextField("id", Bean::getMethod())
> 
> this proposal is correctly preventing the user from assigning a read-only
> model to a component designed to write on it.

Your solution does not prevent this. Your IReadOnlyModel is a subinterface of 
IModel. Therefore it is perfectly fine to pass a IReadOnlyModel to the 
constructor of TextField. In your example, you will need to add a cast or 
assign it to a variable first:

IReadOnlyModel<String> model = Bean::getMethod;
new TextField<>("id", model);

Also, I think this should be allowed. A disabled TextField provides a read-
only view of its model. There are a few read-only usecases in Wicket though: 
for example ListView and the choices in a dropdown select.

> > In Wicket 8 this works, because IModel is a functional interface, so Java
> > knows how to convert a method taking no arguments and returning a double
> > into a IModel<Double> by mapping that method to getObject().
> 
> Sure, and it's our job to provide good a API allowing the user to benefit
> from Java 8 features *where it does make sense*. A good set of constructors
> for a Label would include:
> 
> public Label(String id, IReadyOnlyModel model){ ... }

This would require adding additional constructors to all classes that must 
support read-only models. You cannot replace the constructors, because it is 
perfectly fine to construct a label with a read-write model. The problem is 
that the is-a relation for IReadOnlyModel is defined wrongly: a read-write 
model is a read-only model (a read-write model provides all the capabilities 
of a read-only model and more).

To get this right, IModel needs to be split into 2 super-interfaces: 
IReadOnlyModel and IWriteOnlyModel, both extending IDetachable. IModel then is 
simply a combination of IReadOnlyModel and IWriteOnlyModel. Both super-models 
can be functional interfaces and perhaps we can even support split models on 
components:

new TextField<>("id", Bean::getMethod, Bean::setMethod);

The problem however is "default model". For this to work, we need to drop the 
components default model, because you cannot know if it is IReadOnlyModel, 
IWriteOnlyModel or IModel. This includes CompoundPropertyModel. But this 
breaks the API of Wicket bigtime and the gain turned out the be very small.

Best regards,
Emond

Reply via email to