Pregunta

Me gustaría añadir un método a un tipo integrado (por ejemplo,Doble), así que puedo usar un infix operador.Es eso posible?

¿Fue útil?

Solución

Sí y no.Sí, usted puede hacer parece como se ha añadido un método para double.Por ejemplo:

class MyRichDouble(d: Double) {
  def <>(other: Double) = d != other
}

implicit def doubleToSyntax(d: Double) = new MyRichDouble(d)

Este código añade a la ya no está disponible <> operador a cualquier objeto de tipo Double.Tan largo como el doubleToSyntax el método es en el ámbito de aplicación de modo que pueda ser invocada sin calificación, los siguientes:

3.1415 <> 2.68     // => true

El "no" de parte de la respuesta la da el hecho de que usted realmente no añadir nada a la Double clase.En su lugar, usted está creando una conversión de Double a un nuevo tipo que hace es definir el método que desee.Esta puede ser una técnica más potente de la abrir-clases ofrecidas por muchos de los lenguajes dinámicos.También pasa a ser completamente seguro.:-)

Algunas limitaciones que deben ser conscientes de:

  • Esta técnica no permite quitar o redefinir los métodos existentes, se acaba de agregar nuevos
  • Implícito en el método de conversión (en este caso, doubleToSyntax) debe ser absolutamente en el ámbito de la extensión deseada método a estar disponible

Idiomáticamente, conversiones implícitas son colocados dentro de los objetos singleton y de importación (por ejemplo, import Predef._) o dentro de los rasgos y heredado (por ejemplo, class MyStuff extends PredefTrait).

Leve a un lado:"operadores de infijo" en la Scala son en realidad métodos.No hay magia asociada con la <> método que le permite ser infix, el analizador simplemente acepta de esa manera.También puede utilizar "métodos regulares" como operadores de infijo si te gusta.Por ejemplo, la Stream la clase define un take método que toma un único Int parámetro y devuelve un nuevo Stream.Esto puede ser usado de la siguiente manera:

val str: Stream[Int] = ...
val subStream = str take 5

El str take 5 la expresión es literalmente idéntica a str.take(5).

Otros consejos

Esta característica fue útil para implementar una clase que realiza la estimación de errores:

object errorEstimation {
  class Estimate(val x: Double, val e: Double) {
    def + (that: Estimate) =
      new Estimate(this.x + that.x, this.e + that.e)
    def - (that: Estimate) =
      new Estimate(this.x - that.x, this.e + that.e)
    def * (that: Estimate) =
      new Estimate(this.x * that.x,
                   this.x.abs*that.e+that.x.abs*this.e+this.e*that.e)
    def / (that: Estimate) =
      new Estimate(this.x/that.x,
                   (this.x.abs*that.e+that.x.abs*this.e)/(that.x.abs*(that.x.abs-that.e)))
    def +- (e2: Double) =
      new Estimate(x,e+e2)
    override def toString =
      x + " +- " + e
  }
  implicit def double2estimate(x: Double): Estimate = new Estimate(x,0)
  implicit def int2estimate(x: Int): Estimate = new Estimate(x,0)

  def main(args: Array[String]) = {
    println(((x: Estimate) => x+2*x+3*x*x)(1 +- 0.1))
    // 6.0 +- 0.93
    println(((x: Estimate) => (((y: Estimate) => y*y + 2)(x+x)))(1 +- 0.1))
    // 6.0 +- 0.84
    def poly(x: Estimate) = x+2*x+3/(x*x)
    println(poly(3.0 +- 0.1))
    // 9.33333 +- 0.3242352
    println(poly(30271.3 +- 0.0001))
    // 90813.9 +- 0.0003
    println(((x: Estimate) => poly(x*x))(3 +- 1.0))
    // 27.037 +- 20.931
  }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top