加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 逆变型的方法继承

发布时间:2020-12-16 18:28:39 所属栏目:安全 来源:网络整理
导读:我定义了两个类型类: trait WeakOrder[-X] { self = def cmp(x: X,y: X): Int def max[Y : X](x: Y,y: Y): Y = if (cmp(x,y) = 0) x else y def min[Y : X](x: Y,y) = 0) x else y}trait Lattice[X] { self = def sup(x: X,y: X): X def inf(x: X,y: X): X}
我定义了两个类型类:

trait WeakOrder[-X] { self =>
  def cmp(x: X,y: X): Int
  def max[Y <: X](x: Y,y: Y): Y = if (cmp(x,y) >= 0) x else y
  def min[Y <: X](x: Y,y) <= 0) x else y
}

trait Lattice[X] { self =>
  def sup(x: X,y: X): X
  def inf(x: X,y: X): X
}

我想做以下事情:

trait TotalOrder[-X] extends Lattice[X] with WeakOrder[X] { self =>
  def sup(x: X,y: X): X = max(x,y)
  def inf(x: X,y: X): X = min(x,y)
}

但这是不可能的,因为逆变型X出现在协变位置(sup和inf的返回值).

但是,在语义上这是正确的:max和min的类型签名max [Y&lt ;:X](x:Y,y:Y):Y编码一个事实,即max / min的返回值必须是两个中的一个参数.

我试着做以下事情:

trait TotalOrder[-X] extends Lattice[X] with WeakOrder[X] { self =>
  def sup[Y <: X](x: Y,y: Y): Y = max(x,y)
  def inf[Y <: X](x: Y,y: Y): Y = min(x,y)
}

但是,方法def [Y&lt ;: X](x:Y,y:Y):Y不能继承def sup [X](x:X,y:X):X.编译器抱怨类型签名不匹配.但是前者(具有现场方差注释)强加了比后者签名更强的类型限制.为什么前者不能继承后者呢?如何绕过TotalOrder [-X]的逆变类型限制(从语义上讲,总顺序是逆变的)?

解决方法

这在语义上不正确.应该从协变和逆变的定义中明确,但我会试着给出一个例子:

假设我们有实体的层次结构:

class Shape(s:Float)
class Circle(r:Float) extends Shape(Math.PI.toFloat * r * r)

我们假设您可以创建逆变订单,就像您尝试的那样:

trait CircleOrder extends TotalOrder[Circle] {
   // compare by r
}

trait ShapeOrder extends TotalOrder[Shape] {
  // compare by s
}

根据变形的定义,如Shape<:Circle,
CircleOrder&lt ;: ShapeOrder
(CircleOrder是ShapeOrder的超类型)

假设我们有以CircleOrder为参数的客户端
并用它来比较圈子:

def clientMethod(circleOrder:TotalOrder[Circle]) = {
  val maxCircle = circleOrder.max(???,???) // expected to return Circle
  maxCircle.r // accessing field that is present only in circle
}

然后,根据继承的定义,应该可以通过
ShapeOrder而不是CircleOrder(记住,ShapeOrder是子类型):

clientMethod(new ShapeOrder {/*...*/})

显然它不会起作用,因为客户仍然希望命令返回Circles,而不是Shapes.

我认为在你的情况下,最合理的方法将使用常规泛型.

更新

这是你如何确保类型安全,但它有点难看.

trait WeakOrder[-X] {
      def cmp(x: X,y: X): Int
      def max[T](x: X with T,y: X with T): T =
        if (cmp(x,y) >= 0) x else y
      def min[T](x: X with T,y) <= 0) x else y
    }

    trait Lattice[X] {
      def sup[T](x: X with T,y: X with T): T
      def inf[T](x: X with T,y: X with T): T
    }

    trait TotalOrder[-X] extends Lattice[X] with WeakOrder[X] {
      def sup[T](x: X with T,y: X with T): T = max(x,y)
      def inf[T](x: X with T,y: X with T): T = min(x,y)
    }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读