【发布时间】:2017-05-05 01:35:13
【问题描述】:
当我们只知道对象类型是Any 时,有没有办法强制将函数参数的编译类型设置为函数签名中定义的预期类型?让我用一个简单的例子来演示一下。
鉴于我们已经定义了以下三个函数:
def writeInt(value: Int): Unit { ... }
def writeString(value: String): Unit { ... }
def get(name: String): Any = { ... }
如何在不强制程序员在其程序中引用 writeInt 函数明确声明应该使用 get 返回的内容 .asInstanceOf[Int] 的情况下成功编译以下代码:
writeInt(get("dividend").asInstanceOf[Int]) // this works...
writeInt(get("dividend")) // but this does not :(
由于get 可能返回Any 对象,它可能是Int 和String,有没有一种优雅的方法可以在Scala 中解决它而没有丑陋的@ 987654331@符号?
请注意,在程序的其他部分,我希望能够使用相同的函数分别编写这段代码,而无需再次输入.asInstanceOf[String]:
writeString(get("name").asInstanceOf[String]) // this works...
writeString(get("name")) // but this does not :(
基本上,我知道get("dividend") 返回一个Int 而get("name") 返回一个String。但是我怎样才能让编译器知道它没有太多的混乱呢?
【问题讨论】:
-
我认为简短的回答是“不”。如果你的返回类型是 Any 那么编译器就无法知道。
-
一个想法是让你的 getter 使用类型而不是字符串
def get[Name]: String ... def get[Id]: Long。这里的 Name 和 Id 是您创建的自定义类型。 -
感谢您提出一个有趣的想法,但它不适用于我的用例。字符串不能用类型替换,因为它将是来自外部世界的任意字符串。它实际上可以是任何东西。
-
那么在这种情况下,在编译时很难知道类型。 get("a") 可以是 String,而 get("b") 可以是 Long。我还假设任意数据也可以在运行时存储?
-
嗯,问题是在编译时知道类型并不难,因为我在编译时已经知道它们(长话短说:我将这些信息存储在 HashMap 中保存每个键的类名和实际值),所以这里没有歧义。这意味着我知道 get("a") 是一个字符串,而 get("b") 是一个 Long,并且我在编译时已经掌握了这些信息。问题是,如何在定义“def get(name:String)”方法的代码中以通用方式访问它,而无需对其结果显式调用“asInstanceOf”。
标签: java scala functional-programming