gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 23:16:02 27 4
gpt4 key购买 nike

[编辑如下]

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

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因为案例类的返回类型必然不同,但它们有着相似的目的。出于这个原因,我想将其保留在 trait 中以对常见行为进行建模,这是我发现使其编译的唯一方法。我意识到这违背了 Scala 类型系统的精神,所以我问下面的第一个问题。

然后,另一个类期望 Foo 的子类作为构造函数参数,我不知道如何表示这一点,除了以下内容:
class Qux(foo: Foo) {
val m = foo.method
...
...
}

课后 Qux有些方法需要 val m是对应于 Bar 的特定子类( BazFoo )的类型,但我收到编译错误,例如
... type mismatch;
[error] found : Any
[error] required: Array[String]

所以我有几个问题:
  • 我对 Scala 足够熟悉,相信这是代表我的特定问题的正确方法,但对它不够熟悉,不知道如何解决它。做我想做的事情的正确方法是什么?
  • 另外,有没有办法告诉类(class)Quxm应该被视为由特定 method 返回的值来自 BarBaz ,而不是 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 返回的值中的键值对的 method做事。但是,我现在遇到错误,例如
    [error] Qux.scala:4: type mismatch;
    [error] found : Qux.this.foo.A
    [error] required: Array[String]
    [error] case Bar(sc, _) => BarProcessor(sc, m).doStuff(rows)
    [error] ^

    当我尝试调用 Map 时出现类似的错误- m 上的特定方法当 fooBaz (沿着 value keys is not a member of 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()

    关于scala - 派生类作为类构造函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41819324/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com