2015-01-31 1 views
6

Ich war immer implizite Konvertierungen über mehrere Ebenen herauszufinden, ist nicht möglich, in scala (es sei denn, Sie Ansicht Grenzen definieren: http://docs.scala-lang.org/tutorials/FAQ/context-and-view-bounds.html)implizite Konvertierung über mehrere Ebenen, warum funktioniert das int automatisch doppelt?

Aber es scheint, dass es einen Fehler in der Art System oder eine Inkonsistenz ist. Nach einem Beispiel (angepasst von How can I chain implicits in Scala?)

class A(val n: Double){ 
    def total = n + 10 
} 

object T1{ 
    implicit def toA(n: Double): A = new A(n) 
    val i : Int = 5 
    println(i.total) //Why does this work? 
    println(5.2.total) 
} 

Ich verstehe nicht wirklich, warum die implizite Konvertierung von Int -> Double -> A funktioniert. Kann jemand bitte die Gründe erklären? Danke

+5

Erweiterung Konvertierungen unterscheiden sich von impliziten Konvertierungen: https://developmentality.wordpress.com/2011/01/24/scala-type-inferencing-gotchas/ –

+0

In der Sprachreferenz kann schwache Übereinstimmung helfen zu verstehen (diese sind nicht implizit Konvertierungen): http://www.scala-lang.org/files/archive/spec/2.11/03-types.html#weak-conformance und diese Frage: http://stackoverflow.com/q/3094380 –

Antwort

1

Wie schon von Gabor kommentiert, ist dies due to numeric widening. Wenn Sie mit der Option -print arbeiten, werden Sie sehen, dass eine .toDouble an die i angehängt wird, die es dann ermöglicht, die toAimplicit zu verwenden. Sie können scalac mit dem warn-numeric-widen laufen, und dies wird zumindest geben Sie die folgenden Schritte aus:

<console>:14: warning: implicit numeric widening 
    println(i.total) //Why does this work? 
      ^
4

kommt es vor, über einen anderen Mechanismus, einzigartig für die numerischen Typen, genannt numerische Erweiterung.

SLS 6.26.1 Value Conversions sagt:

Die folgenden fünf impliziten Konvertierungen können auf einen Ausdruck e, die einen Wert Typ T hat angewendet werden, und die mit einem gewissen erwarteten Typ pt-Typ-geprüft.

Static Overloading Auflösung

Typ Instanziierung

Numerische Widening

Zahlenliteral Eingrenzen

Wert Wegwerfen

View-Anwendung

Dynamische Mitglied Selec tion

(Okay, das ist mehr als fünf .... nicht sicher, warum :)

Der eine von Interesse ist numerische Erweiterung:

Wenn e eine primitive Zahlentyp hat Die weakly conforms auf den erwarteten Typ, es ist auf den erwarteten Typ mit einem der numerischen Konvertierungsmethoden toShort, , toInt, toLong, toFloat, toDouble definierterweitert.

3.5.16 Weak Conformance sagt

In einigen Situationen Scala verwendet eine allgemeinere Konformität Beziehung. Ein Typ S entspricht schwach einem Typ T, geschrieben S <: wT, wenn S <: T oder beide S und T primitive Zahlentypen sind und S in der folgenden Reihenfolge T vorausgeht.

Byte <:w Short 
Short <:w Int 
Char <:w Int 
Int <:w Long 
Long <:w Float 
Float <:w Double 

So println(i.total) wird println(i.total.toFloat) weil Int <:w <: Long <: Float.

Java (und C# und viele andere Sprachen) haben numerische Erweiterungen, und Scala entschied sich dafür, es zu behalten.

Beachten Sie, dass das Gegenteil nicht funktioniert: a Float kann nicht implizit in Int über diesen Weg konvertiert werden, da Größe verloren gehen könnte; es ist keine "Erweiterung". Sie können -Ywarn-numeric-widen hinzufügen und eine Warnung erhalten, wenn dies passiert

+0

mindestens jetzt ist es schon korrigiert: 'Die folgenden sieben impliziten Konvertierungen können (...) – pedrorijo91

Verwandte Themen