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 TransientComposite type. This forces the mixin to implement the TransientComposite type, which would normally mean that it would have to implement all methods, including those found in the TransientComposite interface. However, since we are only really interested in implementing the say() method we will mark this by declaring that the Mixin "implements" the TransientComposite type, but is also "abstract". This, using pure Java semantics, makes it possible to avoid having to implement all methods. Zestâ„¢ 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 remaining methods in the TransientComposite 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 TransientComposite type. As long as there is a Mixin implementation declared for the interface specified by the @This injection it will work, since Zestâ„¢ can know how to implement the interface. But since it is not extended by the TransientComposite type there is no way for a user of the TransientComposite to access it. That Mixin becomes an 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 TransientComposite is a bit more tricky. Instead of just instantiating it you have to create a TransientBuilder first, then set the state using .prototypeFor(), 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: