Ho osservato una differenza nell'inferenza di tipo Scala quando applicata a def
e val
.Inferenza di tipo diverso per `def` e` val` in Scala
Utilizzando def
, è possibile definire un metodo nullario astratto const
restituendo un valore di tipo Int => Int
. Quando si implementa const
con una funzione letterale, non devono fornire un tipo di parametro, come si può dedurre dal compilatore:
trait D {
def const: Int => Int
}
object D extends D {
def const = i => i + 1
}
Questo va bene. (Il lato negativo, viene creata una nuova istanza funzione per ogni accesso al D.const
.)
consideri ora una costruzione analoga utilizzando val
:
trait V {
val const: Int => Int
}
object V extends V {
val const = i => i + 1
}
Questo non verrà compilato, avendo con
error: missing parameter type
val const = i => i + 1
^
Perché?
Non è davvero un'idea sicura utilizzare i 'val' astratti in caratteri (può portare a NPE sorprendenti). Mantieni un 'def' nel tratto e sovrascrivilo con un' val' nell'implementazione. Oppure inizia con 'lazy val x: X = sys.error (" override me ")' nel tratto. – ron
Potrebbe avere qualcosa a che fare con la corrispondenza dei pattern? Ogni cosa tra il segno 'def' e il segno uguale' = 'viene trattato come un identificatore, mentre tutto tra' val' e il segno uguale '=' viene trattato come un modello. Solo un'ipotesi ... – agilesteel
@ron, grazie per averlo menzionato, ma in un modo o nell'altro la domanda rimane, poiché l'uso di un 'def' nel tratto e un' val' nell'implementazione porta allo stesso problema. – knuton