繁体   English   中英

在Scala中使用泛型实现特征的正确方法是什么?

[英]What is the correct way to implement trait with generics in Scala?

我有一些简单的特征(在下面的示例中为Entity),这些特征由我的应用中的案例类扩展。 我想创建一个EntityMapper特性,该特性提供一个接口来处理扩展了Entity特性的案例类(在下面的示例中为Foo)。 我以为我应该可以使用泛型和边界相当容易地做到这一点,但是我已经花了几个小时在上面,但我还没有使其正常工作。 下面的代码是我认为应该能够执行的操作,但是由于编译器错误而失败。 错误是

Test.scala:15:错误:值id不是类型参数Foo \\ println(e.id)的成员

package experiment

trait Entity {
    val id: Option[Long]
}

case class Foo(val id: Option[Long] = None) extends Entity

trait EntityMapper {
    def create[E <: Entity](e: E): E
}

object FooMapper extends EntityMapper {
    def create[Foo](e: Foo): Foo = {
        println(e.id)
        e
    }
}

object Main extends App {
    val foo = FooMapper.create(Foo(None))
}

我已经尝试了几种不同的方法来解决问题,但是没有任何效果。 如果我注释掉问题“ println(e.id)”中的行,它会编译,但没有用,因为我无法访问或修改Foo的任何属性。

我尝试对映射器特征使用协变参数,然后将类型提供给FooMapper对象定义,但这会产生相同的错误。 该尝试的代码如下:

trait EntityMapper[+Entity] {
    def create[E <: Entity](e: E): E
}

object FooMapper extends EntityMapper[Foo] {
...
}

我也尝试过通过简单的继承来实现相同的目的,但是我不能正确地限制FooMapper中的类型参数仅采用Foos,我必须使方法签名与特征完全匹配,这就是为什么我开始尝试使用带有泛型的泛型来实现它的原因。类型绑定。 该尝试的代码如下:

trait EntityMapper {
    def create(e: Entity): Entity
}

object FooMapper extends EntityMapper {
    def create(e: Foo): Foo = {
        println(e.id)
        e
    }
}

返回的错误代码为:

Test.scala:13:错误:无法创建对象,因为未在类型(e:experiment.Entity)experiment.Entity的特征EntityMapper中创建方法

(请注意experiment.Entity与experiment.Foo不匹配。Foo:包实验中的Foo类是包实验中特征Entity的子类,但方法参数类型必须完全匹配。)

object FooMapper extends EntityMapper {
       ^

任何帮助将不胜感激。 我正在使用Scala 2.10.3版本。

您可以通过以下几种方式修复错误

1.在特征上指定通用类型约束。

trait EntityMapper[E <: Entity] {
  def create(e: E): E
}

object FooMapper extends EntityMapper[Foo] {
  def create(e: Foo): Foo = {
    println(e.id)
    e
  }
}

2.使用参数化类型

trait EntityMapper {
  type E <: Entity
  def create(e: E): E
}

object FooMapper extends EntityMapper {
  type E = Foo
  def create(e: Foo): Foo = {
    println(e.id)
    e
  }
}

查看Scala:抽象类型与泛型,以获取有关这两种方法的更多背景知识。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM