Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Trust me; you don't <em>want</em> transparent conversion back and forth. This is precisely what the <code>scala.collection.jcl.Conversions</code> functions attempted to do. In practice, it causes a lot of headaches.</p> <p>The root of the problem with this approach is Scala will automatically inject implicit conversions as necessary to make a method call work. This can have some really unfortunate consequences. For example:</p> <pre><code>import scala.collection.jcl.Conversions._ // adds a key/value pair and returns the new map (not!) def process(map: Map[String, Int]) = { map.put("one", 1) map } </code></pre> <p>This code wouldn't be entirely out of character for someone who is new to the Scala collections framework or even just the concept of immutable collections. Unfortunately, it is completely wrong. The result of this function is the <em>same</em> map. The call to <code>put</code> triggers an implicit conversion to <code>java.util.Map&lt;String, Int&gt;</code>, which happily accepts the new values and is promptly discarded. The original <code>map</code> is unmodified (as it is, indeed, immutable).</p> <p>Jorge Ortiz puts it best when he says that you should only define implicit conversions for one of two purposes:</p> <ul> <li>Adding members (methods, fields, etc). These conversions should be to a new type <em>unrelated</em> to anything else in scope.</li> <li>"Fixing" a broken class hierarchy. Thus, if you have some types <code>A</code> and <code>B</code> which are unrelated. You may define a conversion <code>A =&gt; B</code> if and <em>only</em> if you would have preferred to have <code>A &lt;: B</code> (<code>&lt;:</code> means "subtype").</li> </ul> <p>Since <code>java.util.Map</code> is obviously not a new type unrelated to anything in our hierarchy, we can't fall under the first proviso. Thus, our only hope is for our conversion <code>Map[A, B] =&gt; java.util.Map[A, B]</code> to qualify for the second one. However, it makes absolutely no sense for Scala's <code>Map</code> to inherit from <code>java.util.Map</code>. They are really completely orthogonal interfaces/traits. As demonstrated above, attempting to ignore these guidelines will almost always result in weird and unexpected behavior.</p> <p>The truth is that the javautils <code>asScala</code> and <code>asJava</code> methods were designed to solve this exact problem. There is an implicit conversion (a number of them actually) in javautils from <code>Map[A, B] =&gt; RichMap[A, B]</code>. <code>RichMap</code> is a brand new type defined by javautils, so its only purpose is to add members to <code>Map</code>. In particular, it adds the <code>asJava</code> method, which returns a wrapper map which implements <code>java.util.Map</code> and delegates to your original <code>Map</code> instance. This makes the process much more explicit and far less error prone.</p> <p>In other words, using <code>asScala</code> and <code>asJava</code> <em>is</em> the best practice. Having gone down both of these roads independently in a production application, I can tell you first-hand that the javautils approach is much safer and easier to work with. Don't try to circumvent its protections merely for the sake of saving yourself 8 characters! </p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

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