كيف يمكنني تحديد نوع ملزم بالعائمة ومضاعفة على نوع عام في Scala؟

StackOverflow https://stackoverflow.com/questions/3462983

  •  27-09-2019
  •  | 
  •  

سؤال

أنا أكتب بعض فصول المتجهات والمصفوفة البسيطة. تبدو هكذا:

// Vector with Floats
case class Vector3f(x: Float, y: Float, z: Float) {
  def +(v: Vector3f) = Vector3f(x + v.x, y + v.y, z + v.z)
}

// Vector with Doubles
case class Vector3d(x: Double, y: Double, z: Double) {
  def +(v: Vector3d) = Vector3d(x + v.x, y + v.y, z + v.z)
}

إذا واصلت المزيد من الأساليب والفئات مثل Point3F/D ، Vector4F/D ، Matrix3f/D ، Matrix4f/D ... سيكون هذا كثير من العمل. UFF ... لذلك اعتقدت أن الأدوية الجماهيرية يمكن أن تساعد هنا وإزالة التكرار من قاعدة الكود الخاصة بي. فكرت في شيء مثل هذا:

// first I define a generic Vector class
case class Vector3[@specialized(Float, Double) T](x: T, y: T, z: T) {
   def +(v: Vector3[T]) = new Vector3[T](x + v.x, y + v.y, z + v.z)
}

// than I use some type aliases to hide the generic nature
type Vector3f = Vector3[Float]
type Vector3d = Vector3[Double]

والفكرة هي أن برنامج التحويل البرمجي Scala يولد فئات متخصصة لـ Vector3 [Float] و Vector3 [double] مماثلة كما يفعل قالب C ++. لسوء الحظ ، لا بد لي من وضع نوع ملزم بمعلمة النوع [t] من Vector3 بحيث يتم تعريف المشغل + على T. سؤالي: كيف يمكنني كتابة المتجه 3 [Float] بحيث يحتوي على نفس خصائص الأداء مثل Vector3F؟ السياق: أود استخدام فئات Vector3F / Vector3D في رمز اكتشاف التصادم ... لذلك الأداء مهم بالنسبة لي.

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

المحلول

استخدم سياقًا من الكسور:

case class Vector3[@specialized(Float, Double) T : Fractional](x: T, y: T, z: T)  { ...

ثم داخل جسم الفصل ، احصل على مثيل للمشغلين الحسابين:

  val fractOps = implicitly[Fractional[T]]

أخيرًا استيراد أعضائها إلى نطاق الفصل:

  import fractOps._

بعد ذلك يمكنك كتابة عمليات Infix عادية على قيم النوع T المستخدمة داخل الفصل. للأسف ، سيكون عليك استخدام fractOps.div(a, b) بدلاً من a / b للقسمة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top