2012-06-22 4 views
6

Permite tener una clase de utilidad llamada MathUtil.Scala Inicio numérico con constante 0

y se ve así.

abstract class MathUtil(T:Numeric){ 
    def nextNumber(value:T) 
    def result():T 
} 

Permite que una subclase de esta manera

class SumUtil[T:Numeric] extends MathUtil[T]{ 
    private var sum:T = 0 
    override def nextNumber(value:T){ 
    sum = sum + value 
    } 
    override def result():T = sum 
} 

Tengo un problema con la declaración

private var sum:T = 0 

Ahora, tengo para inicializar para sumar a 0. Conjeturaría cualquier numérica tener una manera de representar 0. Soy bastante nuevo para scala. ¿Cómo resuelvo este problema?

+0

Gracias a todos por las respuestas. Tengo una pregunta de seguimiento. Digamos que tengo una clase que tiene un miembro invaluable de tipo MathUtils. – questionersam

Respuesta

11

El Numeric type class instance tiene un método zero que hace lo que quiere:

class SumUtil[T: Numeric] extends MathUtil[T] { 
    private var sum: T = implicitly[Numeric[T]].zero 
    override def nextNumber(value: T) { 
    sum = implicitly[Numeric[T]].plus(sum, value) 
    } 
    override def result(): T = sum 
} 

Tenga en cuenta que también necesita la instancia para el método plus, a menos que se importa Numeric.Implicits._, en cuyo caso se puede utilizar +. También puede limpiar el código un poco por no usar el contexto de sintaxis atado en este caso:

class SumUtil[T](implicit ev: Numeric[T]) extends MathUtil[T] { 
    import Numeric.Implicits._ 
    private var sum: T = ev.zero 
    override def nextNumber(value: T) { 
    sum = sum + value 
    } 
    override def result(): T = sum 
} 

Esto es exactamente equivalente: la versión con destino contexto es el azúcar solo sintáctica para este argumento implícito, pero si es necesario use ese argumento explícitamente (como lo hace aquí, para su zero), me parece más limpio escribir la versión desacralizada.

+0

¡Hola Travis! Es bueno verte publicando aquí (este es Ben de Austin). Desafortunadamente, esta cosa numérica es, IMO, completamente fugly. Resulta que también es lento como el infierno. IMO: todo el mecanismo implícito de Scala es torpe, frágil y difícil de entender, y todavía necesitas otro tipo de chatarra como @specialized, que también está muy pirateado. Creo que esto se expresaría mucho mejor usando la especialización de clase de estilo de C++, que * solo * * funciona * de la manera que todos esperan, esencialmente copiando la implementación con s/int/double/o lo que sea. –

+0

@UrbanVagabond: ¡Hola, Ben! Estoy de acuerdo en que 'Numérico' es un desastre, y no puedo recordar la última vez que lo usé en mi propio código, pero personalmente no creo que el problema sea la forma en que Scala implementa las clases de tipo (que en realidad he crecido). gustar). –

0

Creo que debe haber una pequeña aclaración de lo que está tratando de lograr exactamente. Desde los documentos de Scala, el tipo numérico en sí es genérico. Mi sensación aquí es que lo que realmente quieres es describir una abstracción MathUtil que maneje cualquier Numérico [T] en lugar de subclases de Numérico [_] que es lo que tu código está describiendo actualmente. Aquí está la implementación correcta basada en esa suposición.

//Define a MathUtil that works on any T 
abstract class MathUtil[T] { 
    def nextNumber(value: T) 
    def result(): T 
} 

//Define a SumUtil that works on any T that has an available Numeric 
//Will search implicit scope, but also allows you to provide an 
//implementation if desired. 
class SumUtil[T](implicit n: Numeric[T]) extends MathUtil[T] { 
    //Use the Numeric to generate the zero correctly. 
    private var sum: T = n.zero 
    //Use the Numeric to correctly add the sum and value 
    override def nextNumber(value: T) = sum = n.plus(sum, value) 
    override def result(): T = sum 
} 

//Test that it works. 
val a = new SumUtil[Int] 
val b = List(1,2,3) 

b map a.nextNumber //Quick and dirty test... returns a meaningless list 
println(a.result) //Does indeed print 6 

Si lo anterior no hace lo que desea, por favor aclare su pregunta.

+0

No está bien ... '[T: Numérico]' es un contexto vinculado y se ampliará a '[T] (implícito n: Numérico [T])', por lo que su código es casi el mismo que el de OP excepto para el 'n.zero'. – drexin

Cuestiones relacionadas