有可能这样做吗? (我正在使用scala 2.10)调用一个方法,该方法要求对象具有名为“fullName”的函数,但是使用Dynamic trait构建的对象。编译器抱怨,但也许我做错了。
我不需要这个任何工作,我只是在学习语言。
import scala.language.dynamics
object Main extends App {
class MyStatic {
private var privateName = ""
var lastName = ""
def name_= (n: String) {
privateName = n
}
def name = s"***$privateName***"
def fullName = s"$name $lastName"
}
class MyDynamic extends scala.Dynamic {
val map = collection.mutable.Map[String, String]()
def selectDynamic(key: String): String = map(key)
def updateDynamic(key: String)(value: String) {
map += key -> value
}
def applyDynamic(key: String)(value: Any*) = key match {
case "fullName" => {
val name = map("name")
val lastName = map("lastName")
s"$name $lastName"
}
}
}
def showFullName(o: { def fullName: String }) = s"My full name is $o.fullName"
println("Starting App...")
val s = new MyStatic
s.name = "Peter"
s.lastName = "Parker"
println(showFullName(s))
val d = new MyDynamic
d.name = "Bruce"
d.lastName = "Wayne"
println(showFullName(d))
}
答案 0 :(得分:1)
结构类型{ def fullName: String }
基本上意味着"任何名为fullName
的无法方法返回String
的类型。
MyDynamic
没有这样的方法,因此不符合这种结构类型。 MyDynamic
扩展scala.Dynamic
的事实是无关紧要的:这意味着对于它的任何实例,您都可以像调用fullName
一样执行看起来的内容,但它并不意味着MyDynamic
(作为一种类型)有任何这样的成员。
所以简短的回答是没有,你不能将动态对象与结构类型混合起来。
为了完整性,我必须补充一点,可以按预期工作,但它需要编译器的特殊规定(即,编译器可以考虑比任何类型扩展{{ 1}} - 并实现所需的查找方法 - 与任何结构类型兼容,并且不像通常那样通过反射实现调用,而是通过调用相应的查找方法来实现。
答案 1 :(得分:0)
你正试图将两个完全不同的东西粘在一起。虽然结构类型有时也与'duck-typing'相比较,但它的功能正是使用静态类型信息(即使在使用站点上,字节代码也会调用反射)。根据定义,您的动态类型不具有此类静态类型信息。所以你永远无法说服Scala编译器你的动态类型有一个可以静态验证存在的方法。
唯一的解决方法是在showFullName
中允许任何类型,并使用反射来调用fullName
(同样,我不确定这是否与动态相关对象)。
另一方面,Scala会让您对动态类型做任何事情,将责任交给您:
def showFullName(o: Dynamic) = s"My full name is $o.fullName"
println(showFullName(d))