تمديد سكالا الطبقة التي تمتد أمر
-
10-07-2019 - |
سؤال
أواجه مشكلة في توسيع قاعدة الطبقة التي تمتد أمرت[قاعدة].بلدي فئة مشتقة لا يمكن تمديد أمر[المستمدة] لذلك لا يمكن أن تستخدم رئيسيا في TreeMap.إن إنشاء TreeMap[قاعدة] ثم تجاوز مجرد مقارنة في المستمدة أن يعمل ولكن هذا ليس ما أريد.وأود أن تكون قادرة على فئة مشتقة الرئيسية.هل هناك طريقة للتغلب على هذا ؟
case class A(x: Int) extends Ordered[A] {
def compare(that: A) = x.compare(that.x)
}
// Won't compile
// case class B(val y : Int) extends A(1) with Ordered[B] {
// def compare(that: B) = x.compare(that.x) match {
// case 0 => y.compare(that.y)
// case res => res
// }
// }
// Compiles but can't be used to define a TreeMap key
case class B(y: Int) extends A(1) {
override def compare(that: A) = that match {
case b: B => x.compare(b.x) match {
case 0 => y.compare(b.y)
case res => res
}
case _: A => super.compare(that)
}
}
def main(args: Array[String]) {
TreeMap[B, Int]() // Won't compile
}
تحرير
هذا النقاش على سكالا القائمة البريدية يبدو مهم جدا ولكنه يفقد لي قليلا.
المحلول
يمكنك استخدام نوع التحويل من B إلى أمر[B]:
class OrderedB(me : B) extends Ordered[B]{
def compare(that: B) = me compare that
}
collection.immutable.TreeMap.empty[B, Int](new OrderedB(_))
أعتقد ب دائما إلى نوع فرعي من مما يعني النظام[A] من أبواب نوع ثابتة.فإنه لا يمكن تحديد الثاني مقارنة طريقة لتنفيذ أمر[B] مع نفس النوع errasure كما قارن بين طريقة من أمر[A].
بدلا من ذلك يمكنك تحديد ضمني نوع الإصدارات من B إلى أمر[B]:
implicit def orderedA2orderedB[B <: A with Ordered[A]](b : B) : Ordered[B] = b.asInstanceOf[Ordered[B]]
collection.immutable.TreeMap[B, Int]()
هذا ينبغي أن يكون ساري المفعول.أنا لست على علم وسيلة للتعبير عن هذا في نوع النظام دون أن يلقي.
نصائح أخرى
الصفة Ordered
يأخذ معلمة.نوع المعلمة الممنوحة ، لكنه يعمل تماما مثل أي معلمة أخرى.عندما تقدم مرتين في الفئة الأساسية في فرعية ، أنت لست "استيراد" نسختين من Ordered
.بدلا من ذلك ، linearization من الطبقات يأخذ مكان ، استيراده مرة واحدة فقط.ولهذا السبب لا يمكن تمرير اثنين معلمات مختلفة إلى ذلك.
الآن هناك سبب لماذا TreeMap
لا يتطلب subclass
من Ordered
, فقط التحويل من فئة إلى Ordered
من ذلك.هذا هو بالضبط لجعل مثل هذه الأمور ممكن.بدلا من توسيع نطاق هذه الأشياء مباشرة ، يجب أن implicits لهم:
scala> class A(val x: Int)
defined class A
scala> class B(x : Int, val y : Int) extends A(x)
defined class B
scala> import scala.collection.immutable.TreeMap
import scala.collection.immutable.TreeMap
scala> class AOrd(a: A) extends Ordered[A] {
| def compare(that: A) = a.x.compare(that.x)
| }
defined class AOrd
scala> object AOrd {
| implicit def toAOrd(a: A) = new AOrd(a)
| }
defined module AOrd
scala> class BOrd(b: B) extends Ordered[B] {
| def compare(that: B) = b.x.compare(that.x) match {
| case 0 => b.y.compare(that.y)
| case res => res
| }
| }
defined class BOrd
scala> object BOrd {
| implicit def toBOrd(b: B) = new BOrd(b)
| }
defined module BOrd
scala> import AOrd._
import AOrd._
scala> import BOrd._
import BOrd._
scala> TreeMap[B, Int]()
res1: scala.collection.immutable.SortedMap[B,Int] = Map()
هل يمكن وضع ضمني يأمر[B] في نطاق مكان ما مثل هذا:
object BOrdering extends Ordering[B] {
def compare(a: B, b: B) = a.compare(b)
}
implicit val bo = BOrdering
TreeMap[B, Int]() // Now it works!
تحرير:هذا هو فقط في سكالا 2.8 (شكرا يا كين)