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

scala – 使用Any for Union类型是个好主意吗?

发布时间:2020-12-16 18:49:13 所属栏目:安全 来源:网络整理
导读:我想创建一个类生成器(适用于Avro模型).我有一个问题,因为有时我生成的类的字段可能是许多不同类型之一,让我们说它可能是一个Int或一个字符串或其他什么.简单的想法是使用Any类型创建该字段,并在运行时检查它是否正常. 问题是使用Any丢弃了scala类型系统的一
我想创建一个类生成器(适用于Avro模型).我有一个问题,因为有时我生成的类的字段可能是许多不同类型之一,让我们说它可能是一个Int或一个字符串或其他什么.简单的想法是使用Any类型创建该字段,并在运行时检查它是否正常.

问题是使用Any丢弃了scala类型系统的一些强大功能.代码中的一些错误不会在编译时被捕获(如果我将一个List提供给期望由Any覆盖的String或Int的函数).

例如 :

我的课程有这样的描述:

{"className" : "MyClass","fields" : [
  { "fieldName" : "myField","type" : ["String","Int"]}
]}

从这个描述中,我创建了这个类:

class MyClass(myField: Any)

我想创建这样的东西:

class MyClass(myField: String or Int)

我应该停止使用Any吗?在scala社区中使用Any通常被认为是个好主意吗?

解决方法

Is using Any generally considered a good idea in the scala community?

不.任何意味着没有类型信息,所以它通常被认为是一种不好的做法.

在Scala中,您可以使用Either表示联合类型,但如果联合中有很多可能的类型,它会变得很麻烦.例:

class MyClass(myField: Either[String,Int]) {
  def doSomething = myField match {
    case Left(myStringField) => ???
    case Right(myIntField) => ???
  }
}

另一种可行的方法是在其类型中使MyClass成为通用的:

class MyClass[A](myField: A)

但是这并没有对A的类型设置任何约束.

为了设置约束,例如使它成为类型的有限子集,您可以使用ad-hoc多态:

trait MyConstraint[A]
class MyClass[A: MyConstraint](myField: A)

现在新的MyClass(myValue)将无法编译,除非在范围内存在隐式MyConstraint [A].现在,您可以使用隐式值将要允许的类型列入白名单

implicit object IntConstraint extends MyConstraint[Int]
implicit object StringConstraint extends MyConstraint[String]

例:

new MyClass(42) // ok,there's implicit evidence of MyConstraint[Int]
new MyClass("foo") // ok,there's implicit evidence of MyConstraint[String]
new MyClass(false) // won't compile,no implicit evidence of MyConstraint[Boolean]

在技??术术语中,MyConstraint是一个类型类,用于在MyClass的构造函数中细化类型A.

通过要求为每个实例定义一组操作,您可以进一步表征类型类.例如.

trait MyConstraint[A] {
  def mandatoryOp: A
}

implicit object IntConstraint extends MyConstraint[Int] {
  def mandatoryOp = 42
}

implicit object StringConstraint extends MyConstraint[String] {
  def mandatoryOp = "foo"
}

class MyClass[A](myField: A)(implicit ev: MyConstraint[A]) {
  def doSomething: A = ev.mandatoryOp 
}

请注意,A:MyConstraint只是需要MyConstraint [A]类型的隐式参数的语法糖.在最后一个示例中,我选择了显式语法,以便在范围内使用隐式参数ev.

(编辑:李大同)

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

    推荐文章
      热点阅读