Der Unit
bekommt beim Generieren von Byte-Code eine spezielle Behandlung durch den Compiler, weil er analog zu void
auf dem jvm ist. Aber konzeptionell als ein Typ innerhalb des Scala-Typ-Systems scheint es, dass es auch in der Sprache selbst eine spezielle Behandlung erfährt (Beispiele unten).Welche Sonderregeln hat der Scala-Compiler für den Unit-Typ innerhalb des Typsystems?
Also meine Frage ist, dies zu klären und zu verstehen, welche Mechanismen verwendet werden, und wenn es wirklich eine spezielle Behandlung für die Unit
Art gibt.
Beispiel 1:
Für "normale" scala Typen wie Seq
, wenn eine Methode Seq
zurückgibt, dann müssen Sie Seq
zurückkehren (oder einen spezifischeren Typ, der Seq
erweitert)
def foo1: Seq[Int] = List(1, 2, 3)
def foo2: Seq[Int] = Vector(1, 2, 3)
def foo3: Seq[Int] = "foo" // Fails
Die ersten beiden Beispiele kompilieren, weil List[Int]
und Vector[Int]
Subtypen vonsind. Der dritte schlägt fehl, weil String
nicht ist.
Aber wenn ich das dritte Beispiel ändern Unit
obwohl zurückzukehren, es wird kompilieren und ohne Probleme ausgeführt werden, obwohl String
ist nicht ein Subtyp von Unit
:
def foo3(): Unit = "foo" // Compiles (with a warning)
Ich weiß nicht, von jedem anderen Typ, für den diese Ausnahme in scala erlaubt wäre. Hat der Compiler spezielle Regeln für den Typ Unit
auf der Systemtypebene oder gibt es eine Art allgemeinerer Mechanismus bei der Arbeit, z. eine implizite Konvertierung
Beispiel 2:
Ich bin auch nicht klar, wie Einheit in Situationen, in Wechselwirkung tritt, wo Varianz Regeln normalerweise angewandt werden würden.
Zum Beispiel, wir schlagen manchmal diesen Fehler mit Future[Unit]
wo wir versehentlich map
anstelle von flatMap
und erstellen Future[Future]
:
def save(customer: Customer): Future[Unit] = ... // Save to database
def foo: Future[Unit] = save(customer1).map(_ => save(customer2))
Die map
Schaffung ist ein Future[Future[Unit]]
und der Compiler ein Future[Unit]
erfordert. Doch das kompiliert!
Zuerst dachte ich, das war, weil Future[+T]
covariant ist, aber eigentlich Future[Unit]
ist kein Subtyp von Unit
, damit es nicht, dass zu sein scheint.
Wenn der Typ zu Boolean
beispielsweise geändert wird, erkennt der Compiler den Fehler:
def save(customer: Customer): Future[Boolean] = ...
def foo: Future[Boolean] = save(customer1).map(_ => save(customer2)) // Compiler fails this
Und für jeden anderen nicht Unit
Art wird es nicht kompilieren (außer Any
weil Future[Any]
ein Subtyp sein geschieht von Any
durch Zufall).
Hat der Compiler in diesem Fall spezielle Regeln? Oder gibt es einen allgemeineren Prozess?
im Grunde, wenn Sie irgendeine Art als Einheit (ein Wert oder eine Funktion Rückkehr zum Beispiel) erklären, der Compiler wandelt, was Wert, den es zu Einheit hat. nicht sicher, ob es die Antwort ist, die Sie suchen, oder wenn Sie nach mehr internen Details suchen. – pedrorijo91