0

我在 scala 2.12 上有点挣扎:

我有以下层次结构:

trait A

case class B(format: String) extends A

trait Writer {
  def write(config: A): Unit
}


val writer = new Writer {
  override def write(config: A) = println("hi")
}

val w = B("console")
writer.write(w)

效果很好。但我想为 writer 提供一个替代实现:

val writer = new Writer {
  override def write(config: B) = println("hi")
}

但我明白了object creation impossible, since method write in trait Writer of type (config: Playground.A)Unit is not defined

我假设由于 B 是 A,这应该有效。如何使用wherewrite类型的配置覆盖BB <: A

斯卡斯蒂:https ://scastie.scala-lang.org/QBaiiDP4Sj2lptUjrWLJYw

编辑: - - - - - - - - - - - - - - - - - - - - - - - - ------------

根据一些输入,我将实现更改为:

sealed trait A

case class B(format: String) extends A

trait Writer[+T] {
  def write[S >: T](config: S): Unit
}


val writer: Writer[A] = new Writer[B] {
  override def write[B](config: B) = println("hi")
}


val b = B("console")
writer.write(b)

哪个有效。

但是,如果我修改它以访问 中的变量config,它会中断:

sealed trait A

case class B(format: String) extends A

trait Writer[+T] {
  def write[S >: T](config: S): Unit
}


val writer: Writer[A] = new Writer[B] {
  override def write[B](config: B) = println(config.format)
}


val b = B("console")
writer.write(b)

value format is not a member of type parameter B

https://scastie.scala-lang.org/Xj2rKbbiTmG7raZgQZYfHA

欣赏输入。

4

2 回答 2

1

您与最新版本非常接近。正如 Matthias Berndt 所指出的,该write方法声明了一个的类型参数,但应该使用在 trait 上声明的那个。此外,类型参数应该是逆变的。

此代码编译并打印console

sealed trait A

case class B(format: String) extends A

trait Writer[-T <: A] {
  def write(config: T): Unit
}


val writer: Writer[B] = new Writer[B] {
  override def write(config: B) = println(config.format)
}


val b = B("console")
writer.write(b)

请注意,因为B是 的子类型A,您也可以将 aWriter[A]与 的实例一起使用B。因为Writer是逆变的,所以可以将 type 的值赋给 typeWriter[A]的变量Writer[B]

val aWriter: Writer[B] = new Writer[A]  {
  override def write(config: A) = println(s"Got A: $config")
}

aWriter.write(b) // prints "Got A: B(console)"

您不能做相反的事情(Writer[B]Writer[A]变量赋值),因为 aWriter[A]将能够接受 type 的任何值A,而 aWriter[B]只能接受 type 的值B

https://scastie.scala-lang.org/TimMoore/bd5E1p99TLCDVfMbElKqFg/8

于 2021-12-18T00:29:55.530 回答
1

它不起作用,因为Writer声明它的write方法将接受任意A. 如果有人决定传递一个A不是Btowriter.write怎么办?然后它就行不通了,所以编译器会阻止你这样做。

于 2021-12-16T12:35:07.190 回答