我想创建一个类生成器(适用于Avro模型).我有一个问题,因为有时我生成的类的字段可能是许多不同类型中的一个,让我们说它可能是一个Int
或一个String
或其他什么.简单的想法是使用类型创建该字段,Any
并在运行时检查它是否正常.
问题是使用Any
丢弃scala类型系统的一些强大功能.代码中的一些错误将不会在编译时被捕获(如果我给一个List
期望a String
或Int
覆盖的函数Any
).
例如 :
我的课程有这样的描述:
{"className" : "MyClass", "fields" : [
{ "fieldName" : "myField", "type" : ["String", "Int"]}
]}
Run Code Online (Sandbox Code Playgroud)
从这个描述中,我创建了这个类:
class MyClass(myField: Any)
Run Code Online (Sandbox Code Playgroud)
我想创建这样的东西:
class MyClass(myField: String or Int)
Run Code Online (Sandbox Code Playgroud)
我应该停止使用Any
吗?Any
在scala社区中使用通常被认为是个好主意吗?
在 scala 社区中使用 Any 通常被认为是一个好主意吗?
没有。Any
意味着没有类型信息,因此通常被认为是不好的做法。
在 Scala 中,您可以使用 表达联合类型Either
,尽管如果联合中有很多可能的类型,它会变得很麻烦。例子:
class MyClass(myField: Either[String, Int]) {
def doSomething = myField match {
case Left(myStringField) => ???
case Right(myIntField) => ???
}
}
Run Code Online (Sandbox Code Playgroud)
另一种可行的方法是使其MyClass
类型通用:
class MyClass[A](myField: A)
Run Code Online (Sandbox Code Playgroud)
然而,这并没有对 的类型设置任何限制A
。
为了放置约束,例如使其成为类型的有限子集,您可以使用临时多态性:
trait MyConstraint[A]
class MyClass[A: MyConstraint](myField: A)
Run Code Online (Sandbox Code Playgroud)
现在new MyClass(myValue)
除非有隐含的范围,否则不会编译MyConstraint[A]
。现在您可以将您想要允许使用隐式值的类型列入白名单
implicit object IntConstraint extends MyConstraint[Int]
implicit object StringConstraint extends MyConstraint[String]
Run Code Online (Sandbox Code Playgroud)
例子:
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]
Run Code Online (Sandbox Code Playgroud)
用技术术语来说,MyConstraint
是一个类型类,用于细化 的A
构造函数中的类型MyClass
。
您可以通过要求为其每个实例定义一组操作来进一步表征类型类。例如
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
}
Run Code Online (Sandbox Code Playgroud)
请注意,这A: MyConstraint
只是需要类型为隐式参数的语法糖MyConstraint[A]
。在上一个示例中,我选择了显式语法,以便隐式参数ev
在范围内可用。
归档时间: |
|
查看次数: |
144 次 |
最近记录: |