La primera diferencia práctica es que el vals y objetos perezosos son perezosos, mientras Vals están ansiosos.
La principal diferencia entre los objetos y los vagos perezosos es que un objeto es, desde la perspectiva de los idiomas considerado como un "singleton", que desde la perspectiva de jvm generalmente se trata como un miembro estático.La definición del objeto en el ejemplo dado no puede ser anulada, como otros han demostrado, por la misma razón que los miembros estáticos no pueden ser reemplazados: sin estar atados a una instancia, no hay forma concebible de hacer una búsqueda de función virtual.
object Foo { object Bar extends A; }
está vagamente como el siguiente código java:
class Foo {
private static class Bar extends A{}
public static Bar Bar = new Bar;
}
Si en el ejemplo anterior, si se extiende se definió una subclase C Foo, no sería capaz de anular la definición de Bar. Se accederá a la barra de instancias estáticas en Java como Foo.Bar. C.Bar no significa lo mismo que (nueva C) .Bar. Puede que esté un poco equivocado, en realidad no he intentado descifrar el código scala, esto es solo un ejemplo para ilustrar el concepto general de objetos como miembros estáticos.
lazy vals puede ser un poco menos eficiente. La última vez que revisé, se implementaron al mantener un campo oculto en la clase que mantenía un registro de los valores perezosos que se habían inicializado. Mantener este campo requiere bloqueo, lo que puede causar problemas de rendimiento.
Una importante diferencia práctica entre val perezoso y el objeto es el tratamiento de la insuficiencia:
Si tengo:
class Foo() { throw new Exception("blah!"); }
object Stuff { object Bar extends Foo { val x = "hi" } }
Stuff.Bar
//exception "blah!" thrown.
Stuff.Bar.x
//NoClassDefFoundError: Could not initialize Stuff$Bar$
mientras que si lo hago:
object Stuff2 { lazy val Bar = new Foo() { val x = "hi" } }
Stuff2.Bar
// "blah!"
Stuff2.Bar.x
// "blah!"
El "NoClassDefFoundError" puede ser realmente confuso, y dado que es un error y no una excepción, puede romper el código de manejo de errores que (apropiadamente) atrapa/registra "Excepción" pero permite la propagación de errores. Incluso podría considerar este tipo de error en el lenguaje Scala, ya que este caso de uso indica una condición excepcional, no un verdadero error de JVM. He visto NoClassDefFoundErrors al acceder a objetos que dependían de recursos externos (por ejemplo, conexiones de bases de datos o archivos en el disco). Solo el primer acceso registra la causa subyacente, por lo que la correcta depuración de dicho problema generalmente requiere el reinicio de su servidor de aplicaciones.
Resulta que 'lazy val a3 = new A {def foo = 1}' también debería haberse agregado a la pregunta. – PeWu
Véase también [Scala - nuevo vs objeto se extiende] (http://stackoverflow.com/q/16182735/1048572) – Bergi