Se il metodo ha solo uno o due di default i parametri che possono essere impostati per null
considerare questo modello:
// please note that you must specify function return type
def aMethod (x:String = "asdf"):String = if (x==null) aMethod() else {
// aMethod body ...
x
}
ci sono alcuni vantaggi:
- La definizione metodo indica chiaramente di default del parametro valore.
- Il valore predefinito corretto può essere selezionato dagli strumenti Scala, incluso ScalaDoc.
- Non è necessario definire un valore aggiuntivo per sostituire il parametro originale all'interno del corpo del metodo - meno spazio per errori, più facile da ragionare.
- Il modello è abbastanza conciso.
Inoltre, si consideri il seguente scenario:
trait ATrait {
def aMethod (x:String = "trait's default value for x"):String
}
class AClass extends ATrait {
....
}
Chiaramente, qui dobbiamo estendere il tratto, preservando il valore predefinito originale.Uno dei motivi che coinvolgono inizialmente l'impostazione del parametro null
seguito da un valore predefinito di controllo e reale si romperà il contratto stabilito dal tratto:
class AClass extends ATrait {
// wrong, breaks the expected contract
def aMethod(x: String = null):String = {
val xVal = if (x == null) "asdf" else x
...
}
}
Infatti in questo scenario l'unico modo per preservare il valore originale ATrait
sarà:
class AClass extends ATrait {
override def aMethod (x:String):String = if (x==null) aMethod() else {
... // x contains default value defined within ATrait
}
}
Tuttavia, nello scenario in cui ci sono più di uno o due parametri predefiniti che possono essere impostati per null
il modello comincia a diventare piuttosto disordinato:
// two parameters
def aMethod (x:String = "Hello",y:String = "World"):String =
if (x==null) aMethod(y=y) else
if (y==null) aMethod(x=x) else {
// aMethod body ...
x + " " + y
}
// three parameters
def aMethod (x:String = "Hello",y:String = " ",z:String = "World"):String =
if (x==null) aMethod(y=y,z=z) else
if (y==null) aMethod(x=x,z=z) else
if (z==null) aMethod(x=x,y=y) else {
// aMethod body ...
x + y + z
}
Ancora quando si esegue l'override di un contratto esistente, questo potrebbe essere l'unico modo per rispettare i valori predefiniti originali.
C'è un modo per convertire implicitamente in un'opzione? Certo, potrei scrivere la mia def, ma è già presente nella API? –
@JohnSmith: vuoi dire qualcosa come: 'implicit def obj2Option [T] (t: T) = Option (t)'? Penso che questo sia un po 'troppo fragile/pericoloso per far parte delle conversioni implicite standard, non ne conosco. –
@TomaszNurkiewicz si prega di vedere la mia risposta, poiché questa soluzione, ad un esame più approfondito, avrà un impatto negativo sugli strumenti di sviluppo di Scala e avrà il potenziale per rompere il codice ogni volta che è coinvolta l'ereditarietà. –