نمط تصميم سكالا - سمة مختومة مع عامين ، طريقة الأطفال لها نفس نوع الكائن في قائمة الحجج

1

آسف إذا كان العنوان غير واضح للغاية ، لكني لا أعرف كيف أشرح ذلك. أنا مبتدئ سكالا وأكافح من أجل إيجاد حل لمشكلتي. إليك المقتطف:

sealed trait Base[T, M] {
  var value: Option[T] = None

  def initialize(v: T): this.type = {
    value = Some(v)
    this
  }
  def combine[K <: M](other: K): M

}

class Child1 extends Base[String, Child1] {

  override def combine[K <: Child1](other: K) = {
    val c = new Child1()
    c.initialize(value.get + " - " + other.value.get)
    c
  }

}

class Child2 extends Base[Long, Child2] {
  override def combine[K <: Child2](other: K) = {
    val c = new Child2()
    c.initialize(value.get + other.value.get)
    c
  }
}


object Main extends App {
  val c1a = new Child1()
  c1a.initialize("a")
  val c1b = new Child1()
  c1b.initialize("b")

  val c21 = new Child2()
  c21.initialize(1)
  val c22 = new Child2()
  c22.initialize(2)

  val m1 = Map("child1" -> c1a, "child2" -> c21)
  val m2 = Map("child1" -> c1b, "child2" -> c22)

  m1("child1").combine(m2("child1"))
}

ما أريد تحقيقه هو أن كل فئة فرعية من Base يمكن دمجها فقط مع كائنات من نفس النوع.

المترجم يشكو عند استدعاء combine طريقة بسبب عدم تطابق في نوع الوسيطة. هل هذا نهج صحيح؟ أو بنية الطبقات لغرضي هو إعادة كتابتها؟

تعديل

يجب أن يكون هذا جيدًا أيضًا:

sealed trait Base[T, M] {
  var value: Option[T] = None

  def initialize(v: T): this.type = {
    value = Some(v)
    this
  }
  def combine(other: M): M

}

class Child1 extends Base[String, Child1] {

  override def combine(other: Child1) = {
    val c = new Child1()
    c.initialize(value.get + " - " + other.value.get)
    c
  }

}

class Child2 extends Base[Long, Child2] {
  override def combine(other: Child2) = {
    val c = new Child2()
    c.initialize(value.get + other.value.get)
    c
  }
}

الحل الحالي

الحل الذي وجدته حتى الآن:

val combined = (m1("child1"), m2("child1")) match {
  case (a: Child1, b: Child1) => a.combine(b)
  case _ => throw new Error("Error")
}

1 إجابة

0

What I want to achieve is that each subclass of Base can be combined only with objects of the same type.

بدلا من استخدام تطابق النمط على (m1("child1"), m2("child1")) يمكنك استخدام نوع الاختيار مباشرة combine طريقة على كل فئة الطفل. بالإضافة إلى ذلك ، يبدو أن التعليمات البرمجية الخاصة بك أسلوبًا أكثر إلحاحًا ، مثل الاستخدام var ، لقد قمت بكسر كودك بطريقة أكثر وظيفية.

sealed trait Base[T] {
  val value: Option[T] = None
  def combine[Other](other: Base[Other]): Base[T]
}

case class Child1(override val value: Option[String]) extends Base[String] {
  override def combine[Other](other: Base[Other]) = {
    other match {
      case v: Child1 => this.copy(v.value)
      case _ => throw new Error("Error")
    }
  }
}

case class Child2(override val value: Option[String]) extends Base[String] {
  override def combine[Other](other: Base[Other]) = {
    other match {
      case v: Child2 => this.copy(v.value)
      case _ => throw new Error("Error")
    }
  }
}
val child1 = Child1(Some("child1"))
val child2 = Child2(Some("child2"))
child1.combine(child2)  //Will fail
val anotherChild1 = Child1(Some("Another child1"))
child1.combine(anotherChild1) //Will succeed.
:مؤلف

أسئلة ذات صلة

فوق
قائمة طعام