【问题标题】:Generic traits with companion object带有伴生对象的通用特征
【发布时间】:2015-01-07 02:52:16
【问题描述】:

我正在使用 scala 2.10。我对 scala 仍然(非常)陌生,我无法理解为什么我不能访问 trait Printer[T]print 方法内的 Person 案例类的 name 字段。

这是示例代码: 它打印出来 Person(Mark) Person(Will)

// Model
abstract class BaseModel[T] {
  def all: List[T]
}

case class Person(name: String)
object Person extends BaseModel[Person] {
  val people = Set(Person("Mark"), Person("Will"))
  def all = people.toList.sortBy(_.name)
}

// Controller
trait Printer[T] {
  val model: BaseModel[T]
  def print = model.all.foreach { p =>
    // p.name gives error "value name is not a member of type parameter T"        
    println(p)
  }
}

object PersonPrinter extends Printer[Person] {
    val model = Person
}

// Call
object MyApp extends App {
  PersonPrinter.print
}

【问题讨论】:

  • p 是无约束的T,而不是Person。你还没有说T 有一个name
  • 这种情况下怎么能说是人呢?
  • print方法放到PersonPrinter中。

标签: scala generics traits


【解决方案1】:

如果你对 T 没有任何限制,也就是说,对它提出一些要求,你就不能“知道”你可以调用任何特定的方法(除了 toString、hashCode、equals 和其他一些存在于所有对象上的方法)。

您可以做到这一点的一种方法是完全不使用泛型,而是使用具体:

trait Printable {
  def text: String
}
trait Printer {
  def model: BaseModel[Printable]
  def print = model.all.foreach(p => println(p.text))
}

或者您可以为您的 T 使用一种类型,该类型表达了对 T 允许是什么的要求:

trait Printer[T <: Printable] {
  def model: BaseModel[T]
  def print = model.all.foreach(p => println(p.text))
}

这样,您只能创建 Printer 的实现,其中您输入的具体类型实现了 Printable 特征。

【讨论】:

    【解决方案2】:

    我想这会编译:

    trait Printer[T<:Person] {
      val model: BaseModel[T]
      def print = model.all.foreach { p =>
        // p.name gives error "value name is not a member of type parameter T"        
        println(p.name)
      }
    }
    

    或使用结构类型:

    trait Printer[T<: {val name:String}] {
      val model: BaseModel[T]
      def print = model.all.foreach { p =>
        // p.name gives error "value name is not a member of type parameter T"        
        println(p.name)
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-22
      • 1970-01-01
      • 2019-07-24
      • 1970-01-01
      相关资源
      最近更新 更多