加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 派生类作为类构造函数参数

发布时间:2020-12-16 09:51:46 所属栏目:安全 来源:网络整理
导读:[以下编辑] 我有一个类层次结构,现在大致如下: sealed trait Foo { def method: Any}case class Bar extends Foo { def method: Array[String] = // implementation}case class Baz extends Foo { def method: Map[String,Array[String]] = // implementati
[以下编辑]

我有一个类层次结构,现在大致如下:

sealed trait Foo {
  def method: Any
}

case class Bar extends Foo {
  def method: Array[String] = // implementation
}

case class Baz extends Foo {
  def method: Map[String,Array[String]] = // implementation
}

我给抽象方法一个返回类型Any,因为case类的返回类型必然不同,但它们有着相似的目的.出于这个原因,我想保持它的特性来模拟这种常见行为,这是我发现编译它的唯一方法.我意识到这违背了Scala类型系统的精神,所以我问下面的第一个问题.

然后,另一个类期望Foo的子类作为构造函数参数,我不知道如何表示这个,除了以下内容:

class Qux(foo: Foo) {
  val m = foo.method
  ...
  ...
}

后来在类Qux中有一些方法期望val m是与Foo的特定子类(Bar或Baz)对应的类型,但是我得到的编译错误就像

... type mismatch;
[error]  found   : Any
[error]  required: Array[String]

所以我有几个问题:

>我对Scala足够熟悉,认为这是表达我的特定问题的正确方法,但不熟悉它以了解如何解决它.做我正在做的事情的正确方法是什么?
>另外,有没有办法告诉类Qux m应该被视为Bar或Baz中特定方法返回的值,而不是Foo的抽象方法?

编辑:采用@marios建议的方法(使用抽象类型成员)似乎是朝着正确方向迈出的一步,但现在突然出现类型不匹配.在Qux类中,我现在有

class Qux[X <: Foo](sc: SparkContext,val foo: X) {
  val m: foo.A = foo.method

  def process(rows: DataFrame) = foo match {
    case Bar(sc,_) => BarProcessor(sc,m).doStuff(rows)
    case Baz(sc,_) => BazProcessor(sc,m.keys).doStuff(rows,m.values)
  }
}

其中BarProcessor例如使用Array [String]进行实例化,而BazProcessor需要Baz方法返回的值中的键值对才能完成.但是,我现在得到的错误就像

[error] Qux.scala:4: type mismatch;
[error]  found   : Qux.this.foo.A
[error]  required: Array[String]
[error]     case Bar(sc,m).doStuff(rows)
[error]                                         ^

当我尝试在m上调用特定于Map的方法时,类似的错误会出现,当foo是Baz时(沿着值键的行不是Qux.this.foo.A的成员等).我知道m不是一个真正的Array [String] – 它是A类型的.但是有没有办法告诉Scala将其“翻译”成所需的类型?

解决方法

访问ADT中各个类型的更简单方法是使用抽象类型成员而不是泛型类型参数.

sealed trait Foo {
   type A
   def method: A
}

case object Bar extends Foo {
   type A = Array[String]
   def method: A = Array.empty[String]
}

case object Baz extends Foo {
   type A = Map[String,Array[String]]
   def method: A = Map.empty[String,Array[String]]
}

case class Qux[X <: Foo](foo: X) {
  def m: X#A = foo.method

  // You can then pattern match on m
  def f = m match {
    case a: Baz.A => a.size // Use Baz#A if Baz is a class and not an object
    case b: Bar.A => b.size // Use Bar#A if Bar is a class and not an object
  }
}

使用它(看看返回类型)

@ Qux(Baz).m
res6: Map[String,Array[String]] = Map()

@ Qux(Bar).m
res7: Array[String] = Array()

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读