سؤال

أرغب في إضافة طريقة إلى نوع مدمج (على سبيل المثال.مزدوج)، حتى أتمكن من استخدام infix المشغل أو العامل.هل هذا ممكن؟

هل كانت مفيدة؟

المحلول

نعم و لا.نعم، يمكنك تحقيق ذلك يبدو مثلما قمت بإضافة طريقة ل double.على سبيل المثال:

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

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

يضيف هذا الرمز ما لم يكن متاحًا مسبقًا <> المشغل إلى أي كائن من النوع Double.طالما أن doubleToSyntax الطريقة في نطاقها بحيث يمكن استدعاؤها دون مؤهل، سيعمل ما يلي:

3.1415 <> 2.68     // => true

يأتي الجزء "لا" من الإجابة من حقيقة أنك لا تضيف أي شيء إلى القائمة Double فصل.بدلاً من ذلك، أنت تقوم بإنشاء تحويل من Double إلى نوع جديد يحدد الطريقة التي تريدها.يمكن أن يكون هذا أسلوبًا أقوى بكثير من الفصول المفتوحة التي تقدمها العديد من اللغات الديناميكية.ويصادف أيضًا أنه آمن تمامًا من حيث النوع.:-)

بعض القيود التي يجب أن تكون على دراية بها:

  • هذه التقنية لا تسمح لك بذلك يزيل أو إعادة تعريف الأساليب الحالية، فقط قم بإضافة طرق جديدة
  • طريقة التحويل الضمني (في هذه الحالة، doubleToSyntax) يجب أن يكون ضمن النطاق تمامًا حتى تكون طريقة الامتداد المطلوبة متاحة

اصطلاحا، يتم وضع التحويلات الضمنية داخل كائنات مفردة واستيرادها (على سبيل المثال. import Predef._) أو ضمن السمات والموروثة (على سبيل المثال. class MyStuff extends PredefTrait).

جانبا قليلا:"عوامل تشغيل infix" في Scala هي في الواقع طرق.لا يوجد سحر مرتبط بـ <> الطريقة التي تسمح لها بالتثبيت، فإن المحلل اللغوي يقبلها بهذه الطريقة ببساطة.يمكنك أيضًا استخدام "الطرق العادية" كعوامل تشغيل infix إذا أردت.على سبيل المثال، Stream يحدد الفصل أ take الطريقة التي تأخذ واحدة Int المعلمة وإرجاع جديد Stream.يمكن استخدام هذا بالطريقة التالية:

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

ال str take 5 التعبير مطابق حرفيا ل str.take(5).

نصائح أخرى

وجاءت هذه الميزة في متناول اليد لتطبيق فئة أداء تقدير الخطأ:

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
  }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top