Qi4j

Tutorial 9 - Private and abstract mixins

Now we're going to turn around and see how we can reduce the code needed to implement the HelloWorld example. We will also look at how to hide the Properties from the client code, since Properties are often considered to be implementation details that should not be exposed to clients.

The first thing we will do is remove the behaviour interface, and move the say() method to the Composite type. This forces the mixin to implement the Composite type, which would normally mean that it would have to implement all methods, including those found in the Composite interface. However, since we are only really interested in implementing the say() method we will mark this by declaring that the Mixin "implements" the Composite type, but is also "abstract". This, using pure Java semantics, makes it possible to avoid having to implement all methods. Qi4j will during the initialization phase detect that the Mixin only handles the say() method, and therefore only map it to that specific method. In order to instantiate the Mixin it will generate a subclass which implements the remainding methods in the Composite type, as no-ops. These will never be called however, and is there purely for the purpose of being able to instantiate the Mixin. The Mixin is considered to be an Abstract Fragment.

To hide the state from the client we need to use what is called Private Mixins. A Private Mixin is any mixin that is referenced by another Mixin by using the @This injection, but which is not included in the Composite type. As long as there is a Mixin implementation declared for the interface specified by the @This injection it will work, since Qi4j can know how to implement the interface. But since it is not extended by the Composite type there is no way for a user of the Composite to access it. That Mixin becomes a implementation detail. This can be used either for encapsulation purposes, or for referencing utility mixins that help the rest of the code implement some interface, but which itself should not be exposed.

Since the state is now hidden the initialization of the Composite is a bit more tricky. Instead of just instantiating it you have to create a CompositeBuilder first, then set the state using .stateFor(), and then call newInstance(). This ensures that the state can be set during construction, but not at any later point, other than through publicly exposed methods.

Steps for this tutorial:

  1. Move the say() method into the Composite interface
  2. Remove the behaviour interface
  3. Let the HelloWorldMixin implement the Composite directly
  4. Mark the HelloWorldMixin as abstract and implement only the say() method
  5. Remove the HelloWorldState from the Composite "extends" declaration
  6. Remove the GenericPropertyMixin. The Property methods will be implemented by the standard PropertyMixin declared in the Composite interface instead.

Solution

If you have successfully completed the task, you should end up with the following artifacts;

HelloWorldComposite.javaexternal link
HelloWorldMixin.javaexternal link
HelloWorldState.javaexternal link

Powered by SiteVisionexternal link.