我如何在Scala中将变量从一种类型动态转换为另一种类型

时间:2019-01-14 10:29:51

标签: scala dynamic casting

我想对scala变量进行动态转换,转换类型存储在其他变量或数据库中,或者由用户提供。

我是Scala的新手,主要在python上进行编码。在这里,我们尝试采用Any type输入,并根据数据库中保存的类型查询变量的类型,例如:“ String / Int”和用户定义的类,并在将来进行任何处理之前将其强制转换。

在python中:

eval("str('123')")

在我尝试过的Scala中

var a = 123.05
a.asInstanceOf['Int']

给我错误

  

错误:应该有标识符,但是找到了字符串文字。

我希望代码如下:

var a = 123.05
var b = "Int"
a.asInstanceOf[b]

给我错误

  

错误:未找到:键入b

2 个答案:

答案 0 :(得分:2)

好吧,在这里我必须要详尽无遗,因为由于scala和python在静态和动态类型上的差异,您要尝试做的事情很棘手。

首先,您在Python中所做的不是 类型转换,而是转换。

str(12)
python中的

取整数值12并将其转换为(UTF-8?python中的dunno)字符串。 Scala中的同一件事是

12.toString
同时,

类型转换基本上是对编译器typechecker的一个粉红色承诺,即您知道的更多,它应该相信您。还应避免这种情况,例如害虫,因为您基本上会放弃静态类型检查为您提供的所有安全性。但是在某些情况下这是不可避免的

更基本的术语。假设您有以下Scala代码段

sealed trait Foo
final case class Bar(i:Int) extends Foo
final case class Baz(s:String) extends Foo

val f:Foo = Bar(2)
//won't work because the compiler thinks f is of type Foo due to the type ascription bove
println(f.i)
//will work
println(f.asInstanceOf[Bar].i)

Foo类型可以是Bar或Baz(由于是密封的和最终的,因此称为ADT),但是我们专门告诉编译器将f视为Foo,这意味着我们忘记了特定于 输入是。在这种情况下,您可以使用类型转换,请注意,我们不进行转换,而是告诉编译器它实际上是Bar

现在,这一切都发生在编译时,这意味着您无法根据这样的运行时值进行转换

var a = 123.05
var b = "Int"
a.asInstanceOf[b]

现在,据我了解,您有某种类型的字符串输入,需要根据某种模式进行转换。下面的scalafiddle举了一个如何执行此操作的示例:https://scalafiddle.io/sf/i97WZlA/0

但是请注意,这在scala中利用了一些相当高级的概念来确保类型对齐。

这也将https://scalafiddle.io/sf/i97WZlA/1起作用,但是请注意,如果我们想对out做任何有意义的事情,我们将丢失所有需要进行类型转换的类型信息

EDIT / ADDENDUM:我想我也应该做一个例子,说明如何使用这些值并使模式动态化。

https://scalafiddle.io/sf/i97WZlA/2

作为最后一条警告,请注意,这已经接近编译器可以执行的限制,并且需要进行大量装箱和拆箱以携带类型信息(在SchemaValue中),而且它不是堆栈安全的,并且具有错误的错误处理。该解决方案需要进行认真的工程设计才能使其可行,但它应该可以使想法得以传播

答案 1 :(得分:0)

如果您有一个1 dup ...值,则可以使用StringtoInt来解析该字符串:

toDouble

如果您有一个val s = "123.05" val i = s.toInt val d = s.toDouble 值,那么最好使用Any进行转换:

match

如果其他所有方法都失败,则可以显式选择一个类型,但这不是一个好习惯:

val a: Any = ...

a match {
  case i: Int => // It is an Int
  case d: Double => // It is a Double
  case _ => // It is a different type
}

任何体面的数据库框架都将使您能够读写特定类型的值,因此正确的库应该不是问题。

相关问题