如何 return scala中通用特征的子类型?
How to return subtype of a generic trait in scala?
我正在尝试创建一个工厂模式,return 类型是一个参数化特征,实际的 return 类型将是该特征的子类型,但我不知道泛型类型,所以我不知道如何指定 return 类型。简化版是这样的:
trait Mapper[T] {
def createMap(a: T, b: T): T
}
class MapperA extends Mapper[String]{
override def createMap(a: String, b: String): String = {
a + b
}
}
class MapperB extends Mapper[Int]{
override def createMap(a: Int, b: Int): Int = {
a + b + b + b
}
}
def factory(typeOfMapper: String): Mapper = {
typeOfMapper match {
case "mapperA" => new MapperA()
case "mapperB" => new MapperB()
}
}
val mapper = factory("mapperA")
这会给我错误
trait Mapper takes type parameters
但我事先不知道通用类型。这里的 factory
方法的 return 类型应该是什么?
好吧,你可以 return Mapper[_]
... 这将编译,但并不是很有用,正如评论中指出的那样:你将无法使用return 以任何有意义的方式编辑值,因为 create
的实际类型是未知的。
如果映射器的不同实例总是具有不同的类型参数(至少在同一范围内),那么一个简洁的解决方案是使用隐式:
object Mapper {
implicit def strMapper: Mapper[String] = new MapperA
implicit def intMapper: Mapper[Int] = new MapperB
}
然后在所有可见的地方,您可以这样做:
val m1: Mapper[String] = implicitly[Mapper[String]]
val m2: Mapper[Int] = implicitly[Mapper[Int]]
你也可以这样写你的工厂函数(虽然,我不确定你为什么要这样做):
def mapperFactory[T: Mapper] = implicitly[Mapper[T]]
并像这样使用它:
val m: Mapper[String] = mapperFactory
或者像这样
def intMapper = mapperFactory[Int]
如果你想为相同类型的参数使用不同的映射器,这基本上是相同的想法,只是没有隐式看起来不那么整洁。关键是不同类型的不同工厂:
class Mapper {
def str(`type`: String): Mapper[String] = `type` match {
case "foo" => FooMapper()
case "bar" => BarMapper()
}
def int(`type`: String): Mapper[Int] = `type` match {
case "baz" => BazMapper()
case "bak" => BakMapper()
}
}
val fooMapper = Mapper.str("foo")
val bakMapper = Mapper.int("bak")
我正在尝试创建一个工厂模式,return 类型是一个参数化特征,实际的 return 类型将是该特征的子类型,但我不知道泛型类型,所以我不知道如何指定 return 类型。简化版是这样的:
trait Mapper[T] {
def createMap(a: T, b: T): T
}
class MapperA extends Mapper[String]{
override def createMap(a: String, b: String): String = {
a + b
}
}
class MapperB extends Mapper[Int]{
override def createMap(a: Int, b: Int): Int = {
a + b + b + b
}
}
def factory(typeOfMapper: String): Mapper = {
typeOfMapper match {
case "mapperA" => new MapperA()
case "mapperB" => new MapperB()
}
}
val mapper = factory("mapperA")
这会给我错误
trait Mapper takes type parameters
但我事先不知道通用类型。这里的 factory
方法的 return 类型应该是什么?
好吧,你可以 return Mapper[_]
... 这将编译,但并不是很有用,正如评论中指出的那样:你将无法使用return 以任何有意义的方式编辑值,因为 create
的实际类型是未知的。
如果映射器的不同实例总是具有不同的类型参数(至少在同一范围内),那么一个简洁的解决方案是使用隐式:
object Mapper {
implicit def strMapper: Mapper[String] = new MapperA
implicit def intMapper: Mapper[Int] = new MapperB
}
然后在所有可见的地方,您可以这样做:
val m1: Mapper[String] = implicitly[Mapper[String]]
val m2: Mapper[Int] = implicitly[Mapper[Int]]
你也可以这样写你的工厂函数(虽然,我不确定你为什么要这样做):
def mapperFactory[T: Mapper] = implicitly[Mapper[T]]
并像这样使用它:
val m: Mapper[String] = mapperFactory
或者像这样
def intMapper = mapperFactory[Int]
如果你想为相同类型的参数使用不同的映射器,这基本上是相同的想法,只是没有隐式看起来不那么整洁。关键是不同类型的不同工厂:
class Mapper {
def str(`type`: String): Mapper[String] = `type` match {
case "foo" => FooMapper()
case "bar" => BarMapper()
}
def int(`type`: String): Mapper[Int] = `type` match {
case "baz" => BazMapper()
case "bak" => BakMapper()
}
}
val fooMapper = Mapper.str("foo")
val bakMapper = Mapper.int("bak")