La Chapter 2. Type Less, Do More del libro Programming Scala menzioni:
Quando annotazioni di tipo esplicite sono obbligatori.
In termini pratici, è necessario fornire le annotazioni di tipo esplicite per le seguenti situazioni:
valori di ritorno Metodo nei seguenti casi:
- Quando si chiama esplicitamente il ritorno in un metodo (anche a fine).
- Quando un metodo è ricorsivo.
- Quando un metodo è sovraccarico e uno dei metodi ne chiama un altro. Il metodo di chiamata ha bisogno di un'annotazione del tipo di ritorno.
- Quando il tipo di reso indicato è più generico di quanto previsto, ad es.
Any
.
Esempio:
// code-examples/TypeLessDoMore/method-nested-return-script.scala
// ERROR: Won't compile until you put a String return type on upCase.
def upCase(s: String) = {
if (s.length == 0)
return s // ERROR - forces return type of upCase to be declared.
else
s.toUpperCase()
}
metodi di overload a volte può richiedere un tipo di ritorno esplicito. Quando uno di questi metodi ne chiama un altro, dobbiamo aggiungere un tipo di ritorno a quello che sta facendo la chiamata, come in questo esempio.
// code-examples/TypeLessDoMore/method-overloaded-return-script.scala
// Version 1 of "StringUtil" (with a compilation error).
// ERROR: Won't compile: needs a String return type on the second "joiner".
object StringUtil {
def joiner(strings: List[String], separator: String): String =
strings.mkString(separator)
def joiner(strings: List[String]) = joiner(strings, " ") // ERROR
}
import StringUtil._ // Import the joiner methods.
println(joiner(List("Programming", "Scala")))
I due metodi joiner
concatenare una List
di stringhe insieme.
Il primo metodo accetta anche un argomento per la stringa di separazione.
Il secondo metodo chiama il primo con un separatore "predefinito" di un singolo spazio.
Se si esegue questo script, si verifica il seguente errore.
... 9: error: overloaded method joiner needs result type
def joiner(strings: List[String]) = joiner(strings, "")
Poiché il secondo metodo joiner
chiama il primo, esso richiede un tipo String
ritorno esplicito.Esso dovrebbe essere simile a questo:
def joiner(strings: List[String]): String = joiner(strings, " ")
In sostanza, specificando il tipo di ritorno può essere una buona pratica anche se Scala può dedurre che.
Randall Schulz commenti:
Come una questione di (mio personale) di stile, io do tipi restituiti espliciti per tutti, ma i metodi più semplici (sostanzialmente, uno-liners senza logica condizionale).
Tenere presente che se si consente al compilatore di dedurre il tipo di risultato di un metodo, potrebbe essere più specifico di quanto si desideri. (Per esempio, invece di HashMap Map.)
E dal momento che si può decidere di esporre l'interfaccia minimale nel vostro tipo di ritorno (si veda ad esempio questo SO question), questo tipo di inferenza potrebbe ottenere nel modo.
E circa l'ultimo scenario ("Quando il tipo di ritorno inferito sarebbe più generale di quanto previsto"), Ken Bloom aggiunge:
specificare il tipo restituito quando si desidera che il compilatore di verificare che il codice nella funzione restituisce il tipo che si aspettava
(il codice difettoso che innesca una "più generale di tipo rendimento atteso era:
// code-examples/TypeLessDoMore/method-broad-inference-return-script.scala
// ERROR: Won't compile. Method actually returns List[Any], which is too "broad".
def makeList(strings: String*) = {
if (strings.length == 0)
List(0) // #1
else
strings.toList
}
val list: List[String] = makeList() // ERROR
, che erroneamente interpretato ed List [Qualunque] perché restituendo un elenco vuoto, ma Ken chiamato fuori:
List(0)
non crea una lista con 0 elementi.
Crea un List[Int]
contenente un elemento (il valore 0).
Quindi un List[Int]
su un ramo condizionale e uno List[String]
sull'altro ramo condizionale generalizza a List[Any]
.
In questo caso, il typer non è eccessivamente generico: si tratta di un bug nel codice.
)
Come una questione di (il mio stile personale), io do tipi restituiti espliciti per tutti, ma i metodi più semplici (sostanzialmente, uno-liners senza logica condizionale). Tenere presente che se si consente al compilatore di dedurre il tipo di risultato di un metodo, potrebbe essere più specifico di quanto si desideri. (Ad es., 'HashMap' invece di' Map'.) –
@Randall yes, buon punto (sul tipo di ritorno che è troppo specifico). – Jesper