【问题标题】:Scala: abstract comparison method in traitScala:特征中的抽象比较方法
【发布时间】:2019-02-20 18:12:16
【问题描述】:

我有一个要在子类中实现的具有大小比较功能的特征:

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,它们是相同的,但我认为编译器还不知道这一点。


关于如何让这样的事情发挥作用的任何想法?我已经到处寻找答案,但找不到任何东西。也许我不知道该问什么问题。

【问题讨论】:

    标签: scala comparison abstract traits


    【解决方案1】:

    您可以使用F-Bounded 多态性 (这将是Java上的解决方案),或Typeclasses 多态性 (这将是 Haskell 上的解决方案)
    我个人的偏好是使用类型类,因为它更具可扩展性、可维护性和类型安全性 - Here 是 Rob Norris 更客观的比较。

    F 界。

    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
    

    【讨论】:

    • 我在进行初始搜索时发现了一些关于 F-Bounded polymorphism here 的信息,但我最终没有这样做,因为我已经在很多其他地方使用了该特征通过并重构以添加类型参数。不过,这绝对是更优雅的方式。
    【解决方案2】:

    您可以使用以下方法修复第一种方法:

    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
        }
    
    }
    

    【讨论】:

    • 啊,我应该知道模式匹配可以解决它,就像 Scala 中的大多数东西一样!如果从头开始,我认为 Luis 的答案可能更适合可扩展性,但这是快速解决问题的好方法。
    猜你喜欢
    • 1970-01-01
    • 2011-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-19
    • 1970-01-01
    • 1970-01-01
    • 2011-05-14
    相关资源
    最近更新 更多