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

scala – 在通配符上键入Boundary“Stickyness”

发布时间:2020-12-16 18:15:37 所属栏目:安全 来源:网络整理
导读:我在 scala论坛上遇到了这个 post. 这是一个回顾: I just realized that the Scala compiler does not seem to “carry over” type boundaries on wildcards: scala class Foo { def foo = 42 }defined class Fooscala class Bar[A : Foo](val a: A)define
我在 scala论坛上遇到了这个 post.

这是一个回顾:

I just realized that the Scala compiler does not seem to “carry over” type boundaries on wildcards:

scala> class Foo { def foo = 42 }
defined class Foo
scala> class Bar[A <: Foo](val a: A)
defined class Bar
scala> def bar(x: Bar[_]) = x.a.foo
:7: error: value foo is not a member of Any

I would expect that the parameter of method bar is still upper-bound by Foo,even though its exact type parameter is unimportant in the method.
Is there a specific reason for this behavior?

然后讨论进入Spec解释争议:)

说明?

最后海报提出了这样的解释:

However,if the compiler did this for Bar[_],for consistency reasons it would also have to do it for Bar[A]. The latter however would have some strange consequences.
def bar[A](x: Bar[A],y: Bob[A])
for example would suddenly have to carry an implicit type bound for Bob. If Bob had its own type bound things would be really messy.

我不明白,因为

def bar[A](x: Bar[A])

因为Bar类型参数是有界的,所以不会单独编译.

无论如何,我相信以下将是完全有道理的:

def bar(x: Bar[_],y : Bob[_])

解决方法

作为一种解决方法,他们建议:

def bar(x: Bar[_ <: Foo]) = x.a.foo

除了不干燥之外,它会让事情变得困难:

让我们考虑一棵树

abstract class Tree[T <: Tree[T]] { val subTree : List[T] }

现在,您将如何定义递归遍历树的函数(显然在Tree类之外定义):

def size( tree : Tree[_] ) = tree.subTree.size + tree.subTree.map(size(_)).sum

显然不会工作,因为subTree将变成List [Any],所以我们需要一个类型参数:

def size[T <: Tree[T]]( tree : T ) = ...

甚至更丑陋:

class OwnATree( val myTree : Tree[_] ){}

应该成为

class OwnATree[T <: Tree[T]]( val myTree : T ){}

等等……

我相信某处出了点问题:)

解决方法

使用大小和OwnATree完成所需的最简单方法是使用存在类型:

def size(tree: Tree[T] forSome { type T <: Tree[T] }): Int =
  tree.subTree.size + tree.subTree.map(size(_)).sum

和:

class OwnATree(val myTree: Tree[T] forSome { type T <: Tree[T] })

你的Tree [_]版本实际上也在使用存在类型 – 它们只是包含在一些语法糖中.换一种说法,

def size(tree: Tree[_]): Int = ...

只是语法糖:

def size(tree: Tree[T] forSome { type T }): Int = ...

你不能将你需要的约束添加到下划线版本,但你可以添加到desberared版本.

(编辑:李大同)

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

    推荐文章
      热点阅读