首页 > 解决方案 > 如何在Scala中将变量从一种类型动态转换为另一种类型

问题描述

我想为 scala 变量进行动态转换,转换类型存储在不同的变量或数据库中或由用户提供。

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

在蟒蛇中:

eval("str('123')")

在斯卡拉我试过

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

给我错误

错误:需要标识符,但找到字符串文字。

我希望代码如下:

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

给我错误

错误:未找到:类型 b

标签: scaladynamiccasting

解决方案


好的,所以我必须在这里相当详尽,因为由于 scala 和 python 的静态与动态类型差异,您尝试做的事情很棘手。

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

str(12)

在 python 中,取整数值 12 并将其转换为 (UTF-8 ? dunno in python) 字符串。scala中的同样的事情是

12.toString

与此同时,类型转换基本上是对编译器类型检查器的一个小小的承诺,你知道的比它多,它应该相信你。它也应该像害虫一样被避免,因为你基本上放弃了静态类型检查给你的所有安全性。但是在某些情况下是不可避免的

在更基本的方面。假设您有以下 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

编辑/附录:我想我还应该做一个关于如何使用这些值并使模式动态的示例。

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

最后要注意的是,这已经接近编译器可以做的极限,并且需要大量的装箱和拆箱来携带类型信息(in SchemaValue),而且它不是堆栈安全的并且具有乏善可陈的错误处理。这个解决方案需要一些严肃的工程才能实现,但它应该让这个想法得到理解


推荐阅读