سؤال

أواجه مشكلة في توسيع قاعدة الطبقة التي تمتد أمرت[قاعدة].بلدي فئة مشتقة لا يمكن تمديد أمر[المستمدة] لذلك لا يمكن أن تستخدم رئيسيا في 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 (شكرا يا كين)

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