Frage

Ich mag eine Methode zu einem eingebauten Typ (z Doppel) hinzuzufügen, so dass ich einen infix Operator verwenden kann. Ist das möglich?

War es hilfreich?

Lösung

Ja und nein. Ja, können Sie es scheinen wie Sie eine Methode, um double hinzugefügt haben. Zum Beispiel:

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

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

Dieser Code fügt die zuvor nicht verfügbar <> Betreiber auf ein beliebiges Objekt vom Typ Double. Solange die doubleToSyntax Methode in ihrem Umfang ist, so dass sie ohne Qualifikation geltend gemacht werden könnten, werden folgende Arbeiten:

3.1415 <> 2.68     // => true

Der „Nein“ ein Teil der Antwort kommt von der Tatsache, dass Sie nicht wirklich etwas auf die Double Klasse hinzufügen. Stattdessen werden Sie eine Konvertierung von Double auf eine neue Art zu schaffen, die die Methode, die Sie wollen nicht definiert. Dies kann durch viele dynamischen Sprachen angeboten eine viel leistungsfähige Technik als die Open-Klassen sein. Es kommt auch vollständig typsicher zu sein. : -)

Einige Einschränkungen sollten Sie sich bewusst sein von:

  • Diese Technik ermöglicht es Ihnen nicht zu entfernen oder neu zu definieren bestehende Methoden, fügen Sie einfach neue
  • Die implizite Umwandlungsmethode (in diesem Fall doubleToSyntax) absolut in-Bereich für die gewünschten Nebenverfahren zur Verfügung stehen muss

idiomatically werden implizite Konvertierungen entweder innerhalb Singleton Objekte platziert und importiert (z.B. import Predef._) oder innerhalb von Eigenschaften und vererbt (z.B. class MyStuff extends PredefTrait).

Leichte beiseite: „Infixoperatoren“ in Scala sind eigentlich Methoden. Es gibt keine magische mit dem <> Verfahren verbunden, die es Infix sein kann, einfach der Parser akzeptiert es auf diese Weise. Sie können auch „normale Verfahren“ als Infixoperatoren verwenden, wenn Sie möchten. Zum Beispiel definiert die Klasse ein Stream take Verfahren, die einen einzelnen Int Parameter annimmt und gibt eine neue Stream. Dies kann auf folgende Weise verwendet werden:

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

Der str take 5 Ausdruck ist buchstäblich identisch mit str.take(5).

Andere Tipps

Mit dieser Funktion kam praktisch eine Klasse leistungsFehlerAbschätzung zu implementieren:

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
  }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top