Поверь мне; Вы не хотите прозрачного преобразования туда и обратно. Это именно то, что пытались сделать функции scala.collection.jcl.Conversions
. На практике это вызывает много головных болей.
Корень проблемы этого подхода в том, что Scala автоматически внедрит неявные преобразования по мере необходимости, чтобы заставить вызов метода работать. Это может иметь некоторые действительно печальные последствия. Например:
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
}
Этот код не был бы совершенно не характерным для тех, кто не знаком с фреймворком коллекций Scala или даже с концепцией неизменяемых коллекций. К сожалению, это совершенно неправильно. Результатом этой функции является такая же карта . Вызов put
запускает неявное преобразование в java.util.Map<String, Int>
, которое с радостью принимает новые значения и быстро отбрасывается. Оригинал map
не изменен (поскольку он действительно неизменен).
Хорхе Ортис считает, что лучше всего указывать неявные преобразования только для одной из двух целей:
- Добавление членов (методы, поля и т. Д.). Эти преобразования должны быть к новому типу , не связанному с чем-либо еще в области видимости.
- «Исправление» нарушенной иерархии классов. Таким образом, если у вас есть некоторые типы
A
и B
, которые не связаны. Вы можете определить преобразование A => B
, если и только , если вы предпочитаете иметь A <: B
(<:
означает «подтип»).
Поскольку java.util.Map
, очевидно, не является новым типом, не связанным ни с чем в нашей иерархии, мы не можем попасть под первое условие. Таким образом, наша единственная надежда состоит в том, что наше преобразование Map[A, B] => java.util.Map[A, B]
может претендовать на второе. Тем не менее, Scala не имеет никакого смысла наследовать Map
от java.util.Map
. Они действительно полностью ортогональные интерфейсы / черты. Как показано выше, попытка игнорировать эти рекомендации почти всегда приводит к странному и неожиданному поведению.
Правда в том, что методы javautils asScala
и asJava
были разработаны для решения именно этой проблемы. В javautils есть неявное преобразование (на самом деле их несколько) из Map[A, B] => RichMap[A, B]
. RichMap
- это совершенно новый тип, определенный javautils, поэтому его единственная цель - добавить членов в Map
. В частности, он добавляет метод asJava
, который возвращает карту-оболочку, которая реализует java.util.Map
и делегирует ваш исходный экземпляр Map
. Это делает процесс намного более явным и намного менее подверженным ошибкам.
Другими словами, использование asScala
и asJava
является лучшей практикой. Пройдя обе эти дороги независимо друг от друга в производственном приложении, я могу из первых рук сказать, что подход javautils намного безопаснее и с ним легче работать. Не пытайтесь обойти его защиту только ради спасения себя 8 символов!