Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>A lot of the problems that people have with mix-ins can be averted in Scala if you only mix-in abstract traits into your class definitions, and then mix in the corresponding concrete traits at object instantiation time. For instance</p> <pre><code>trait Locking{ // abstract locking trait, many possible definitions protected def lock(body: =&gt;A):A } class MyService{ this:Locking =&gt; } //For this time, we'll use a java.util.concurrent lock val myService:MyService = new MyService with JDK15Locking </code></pre> <p>This construct has several things to recommend it. First, it prevents there from being an explosion of classes as different combinations of trait functionalities are needed. Second, it allows for easy testing, as one can create and mix-in "do-nothing" concrete traits, similar to mock objects. Finally, we've completely hidden the locking trait used, and even that locking is going on, from consumers of our service. </p> <p>Since we've gotten past most of the claimed drawbacks of mix-ins, we're still left with a tradeoff between mix-in and composition. For myself, I normally make the decision based on whether a hypothetical delegate object would be entirely encapsulated by the containing object, or whether it could potentially be shared and have a lifecycle of its own. Locking provides a good example of entirely encapsulated delegates. If your class uses a lock object to manage concurrent access to its internal state, that lock is entirely controlled by the containing object, and neither it nor its operations are advertised as part of the class's public interface. For entirely encapsulated functionality like this, I go with mix-ins. For something shared, like a datasource, use composition.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload