How to use companion factory objects as strategy?

让人想犯罪 __ 提交于 2019-12-08 03:59:54

问题


I have a test which fails intermittently because of ordering issues when I iterate over the values in a Map.

Scala helpfully provides a ListMap which makes the tests stable, at the expense of performance. So I abstracted the ImmutableMapFactory as a val and use it in my code.

class C {
  val immutableMapFactory = scala.collection.immutable.Map

  def func = {
    ...
    immutableMapFactory(pairs :_*)
  }
}

Now my plan was to extend C and override immutableMapFactory for tests

class TestableC extends C {
  override val immutableMapFactory = scala.collection.immutable.ListMap
}

Unsurprising this fails as ListMap does not have the same type as Map. How should I specify the type of the val (or a def) so that I can use the factory wherever I need to create a Map?


回答1:


Your problem is in this line:

val immutableMapFactory = scala.collection.immutable.Map

This makes immutableMapFactory equal to the singleton object Map. ListMap (the singleton) is not a subclass of Map (the singleton), so the subsequent override fails.

If you instead take the apply method from Map, and partially apply it to form a first class function (of type (A, B)* => immutable.Map[A,B]) then the technique can be made to work:

import collection.immutable

class Bip {
  def fac[A,B] = immutable.Map.apply[A,B] _
}

class Bop extends Bip {
  override def fac[A,B] = immutable.ListMap.apply[A,B] _
}



回答2:


Two possible ways. First, using def and functions, which I think is a better abstraction.

class C {
  def immutableMapFactory[A,B]: ((A,B)*) => Map[A,B] = scala.collection.immutable.Map.apply _
}

class TestableC extends C {
  override def immutableMapFactory[A,B] = scala.collection.immutable.ListMap.apply _
}

Second, using val, and structural types:

class C {
  val immutableMapFactory: { def apply[A,B](t: (A,B)*): Map[A,B] } = scala.collection.immutable.Map
}

class TestableC extends C {
  override val immutableMapFactory: { def apply[A,B](t: (A,B)*): Map[A,B] } = scala.collection.immutable.ListMap
}


来源:https://stackoverflow.com/questions/7882777/how-to-use-companion-factory-objects-as-strategy

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!