Scala: абстрактный метод сравнения по признаку - PullRequest
0 голосов
/ 20 февраля 2019

У меня есть черта с функцией сравнения размеров, которую я хочу реализовать в подклассе:

trait A {
    def isLessThan(that: A): Boolean
    ...
}
class SubOfA() extends A {
    ...
    override def isLessThan(that: SubOfA): Boolean = {
        this.size < that.size
    }
    ...
}

Однако метод не является корректным переопределением, поскольку тип аргумента SubOfA а не A.


Я также пытался сделать тип аргумента this.type, но затем, когда я вызываю метод из абстрактной установки, я не могу использовать объект типаA в качестве аргумента:

...
(foo: A, bar: A) => foo.isLessThan(bar)

Это ожидало бы тип foo.type, а не A, которые одинаковы, но я не думаю, что компилятор еще знает об этом.


Есть идеи, как я мог заставить что-то подобное работать?Я искал повсюду, чтобы найти ответ на этот вопрос, но ничего не могу найти.Может быть, я не знаю, какой правильный вопрос задать.

Ответы [ 2 ]

0 голосов
/ 20 февраля 2019

Вы можете использовать F-Bounded полиморфизм (который будет решением для Java ) или Typeclasses полиморфизм (что было бы решением для Haskell ) .
Мое личное предпочтение - использовать классы типов, потому что он более расширяемый, обслуживаемый и более безопасный - Здесь это более объективное сравнение Роба Норриса.

F-Bounded.

trait Comparable[A <: Comparable[A]] { this: A =>
  def isLessThan(that: A): Boolean
}

class SubOfComparable extends Comparable[SubOfComparable] {
  val size: Int = ???
  override final def isLessThan(that: SubOfComparable): Boolean =
    this.size < that.size
}

Типы классов.

trait Comparator[T] {
  def isLessThan(a: T, b: T): Boolean
}

object syntax {
  object comparator {
    implicit final class ComparatorOps[T](val self: T) extends AnyVal {
      final def < (that: T)(implicit C: Comparator[T]): Boolean =
        C.isLessThan(self, that)
    }
  }
}

class Sub {
  final val size: Int = ???
}

object Sub {
  implicit val SubComparator: Comparator[Sub] = new Comparator[Sub] {
    override final def isLessThan(a: Sub, b: Sub): Boolean =
      a.size < b.size
  }
}

import syntax.comparator._
val a = new Sub(...)
val b = new Sub(...)
a < b
0 голосов
/ 20 февраля 2019

Первый метод можно исправить с помощью:

class SubOfA() extends A {

    override def isLessThan(that: A): Boolean = that match {
        case that : subOfA =>  this.size < that.size
        case _ => throw new UnsupportedOperationException("Wrong comparison") //or whatever behaviour deemed suitabe here
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...