[FIXED] scala typemimatch _$1 anstelle des erforderlichen Typs gefunden

Ausgabe

Ich verwende Scala 2.11. Ich habe eine Frage zu den generischen Scala-Typen und dem Musterabgleich.

In der Klasse MyImpl.example()ist Compiler unglücklich zu sagentype mismatch, Required: _$1, Found: X[_ <: A]

trait A

class B extends A

class C extends A

trait Foo[T <: A] {
  def foo(arg: T): Unit
}

class Bar extends Foo[B] {
  override def foo(arg: B): Unit = print("Bar")
}

class Car extends Foo[C] {
  override def foo(arg: C): Unit = print("Car")
}


class MyImpl {

  def getA(): A = {
    new B()
  }

  def example(): Unit = {
    getFoo("1").foo(getA())
  }

  def getFoo(something: String): Foo[_ <: A] = {
    //return either
    something match {
      case "1" => new Bar()
      case "2" => new Car()
    }
  }
}

object Test {
  def main(args: Array[String]) = {
    new MyImpl().example()
  }
}

Hinweis: getFoo(“1”) ist in meinem realen Fall dynamischer, hier ist nur ein Beispiel.

Ich verstehe das irgendwie, der Compiler kann nicht vorhersagen, auf welchem ​​​​Paar der 2-Implementierung die Methode aufgerufen wird.

Ich kann dies umgehen, wenn ich die Implementierung von MyImpl.example()zu ändere

def example(): Unit = {
    (getFoo("1"), getA()) match {
      case (i: Bar, j: B) => i.foo(j)
      case (i: Car, j: C) => i.foo(j)
    }
  }

Ich bin nicht wirklich glücklich damit, da ich mich nur wiederholei.foo(j)

Gibt es einen Scala-Funktionsstil, der viel saubereren Code schreibt?

Lösung

Im Grunde wollen Sie so etwas wie

(getFoo("1"), getA()) match {
  case (i: Foo[t], j: t) => i.foo(j) // doesn't compile, not found: type t
}

oder

(getFoo("1"), getA()) match {
  case (i: Foo[t], j: Id[t]) => i.foo(j) // doesn't compile, t is already defined as type t
}

type Id[T] = T

Sie können die Codeduplizierung in entfernen

def example(): Unit = {                    // (*)
  (getFoo("1"), getA()) match {
    case (i: Bar, j: B) => i.foo(j)
    case (i: Car, j: C) => i.foo(j)
  }
}

(oder Kompilierung von beheben getFoo("1").foo(getA()))

mit verschachteltem Musterabgleich

getFoo("1") match {
  case i => getA() match {
    case j: i._T => i.foo(j)
  }
}

wenn Sie Typmitglied hinzufügen_T

trait Foo[T <: A] {
  type _T = T
  def foo(arg: T): Unit
}

Für getFoo("1")und getAHerstellung new Bdieser Drucke Bar, umgekehrt für getFoo("2")und new Cdiese Drucke Car, für andere Kombinationen wirft dies ClassCastExceptionähnlich wie (*).

Bitte beachten Sie, dass dies nicht einfach als Variablendeklaration und Einzelmusterabgleich umgeschrieben werden kann

val i = getFoo("1")
getA() match {
  case j: i._T => i.foo(j)
}
//type mismatch;
// found   : j.type (with underlying type i._T)
// required: _$1

denn für den verschachtelten Musterabgleich werden die Typen korrekt abgeleitet ( i: Foo[t], j: t), aber für val iden Typ ist existenziell ( auch bekannt als nach der i: Foo[_]Skolemisierung , ).i: Foo[_$1]j: _$1


Beantwortet von –
Dmytro Mitin


Antwort geprüft von –
Timothy Miller (FixError Admin)

0 Shares:
Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like