Derived classes as parameters of a class constructor

[EDIT BELOW]

I have a class hierarchy that right now looks something like this:

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
}

I give the abstract method a return type Any, because the return types of the case classes are necessarily different, but they have a similar purpose. For this reason, I would like to keep this in the dash in order to simulate this usual behavior, and this is the only way I found to compile it. I understand that this is contrary to the spirit of a system like Scala, so I ask the first question below.

Then another class expects a subclass Fooas a constructor parameter, and I don’t know how to denote it except the following:

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

Qux , , val m , (Bar Baz) Foo,

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

, :

  • Scala, , , , , . , ?
  • , Qux, m , method 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 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, Foo Baz ( value keys is not a member of Qux.this.foo.A ..). , m Array[String] - A. Scala "" ?

+4
2

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()
+4

:

sealed trait Foo[A] {
  def method: A
}

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

case class Baz extends Foo[Map[String, Array[String]]] {
  def method: Map[String, Array[String]]
}
+3

Source: https://habr.com/ru/post/1667600/


All Articles