1

是否有可能做到这一点?(我使用的是 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))

}
4

2 回答 2

1

结构类型{ def fullName: String }基本上意味着“任何具有名为fullName返回 aString的 无参数方法的类型MyDynamic都没有这样的方法,因此不符合这种结构类型。MyDynamic扩展的事实scala.Dynamic是无关紧要的:这意味着对于它的任何实例,你可以执行看起来像是对 的调用fullName,但这并不意味着MyDynamic(作为一种类型)具有任何此类成员。

所以简短的回答是否定的,你不能将动态对象与结构类型混合在一起。

为了完整起见,我必须补充一点,它可以按您的预期工作,但它需要编译器的特殊规定(即,编译器可以考虑比任何类型扩展scala.Dynamic- 并实现所需的查找方法 - 兼容使用任何结构类型,并且不是像通常那样通过反射来实现调用,而是通过调用相应的查找方法)。

于 2013-04-03T21:55:41.313 回答
0

你试图把两个完全不同的东西粘在一起。虽然结构类型有时也被比作“鸭子类型”,但它的特点正是使用静态类型信息(即使在使用站点上字节码会调用反射)。根据定义,您的动态类型没有此类静态类型信息。所以你永远无法让 Scala 编译器相信你的动态类型有一个可以静态验证存在的方法。

唯一的解决方法是允许输入任何类型showFullName并使用反射来调用fullName(同样,我不确定这是否与动态对象一起使用)。


另一方面,Scala 将允许你对动态类型做任何事情,将责任交给你:

def showFullName(o: Dynamic) = s"My full name is $o.fullName"

println(showFullName(d))
于 2013-04-03T21:55:16.593 回答