简体   繁体   English

在Scala中将动态对象与结构化类型混合

[英]Mixing dynamic objects with structural typing in Scala

Is it possible to do this? 是否有可能做到这一点? (I'm using scala 2.10) To call a method that requires that the object has a function named "fullName", but the object being built with the Dynamic trait. (我正在使用scala 2.10)调用一个方法,该方法要求该对象具有一个名为“ fullName”的函数,但该对象是使用Dynamic trait构建的。 The compiler complains, but maybe I'm doing it wrong. 编译器抱怨,但是也许我做错了。

I don't need this for any job, I'm just learning the language. 我不需要这份工作,我只是在学习语言。

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))

}

The structural type { def fullName: String } basically means "any type with a no-arg method named fullName returning a String . MyDynamic has no such method, and thus does not comply with this structural type. The fact that MyDynamic extends scala.Dynamic is irreleveant: it means that for any instance of it, you can perform what looks like a call to fullName , but it does not mean that MyDynamic (as a type) has any such member. 结构类型{ def fullName: String }基本上表示“具有MyDynamic方法,名为fullName返回String任何类型MyDynamic没有这种方法,因此不符合此结构类型MyDynamic扩展了scala.Dynamic是irreleveant:这意味着它的任何实例,您可以执行什么看起来像一个电话fullName ,但它并不意味着MyDynamic (作为一种类型)具有任何该等成员。

So the short answer is no , you cannot mix dynamic objects with structural typing like that. 因此,简短的答案是“ 否” ,您不能将动态对象与这样的结构类型混合使用。

For completeness, I must add that it could be made to work as you expected, but it would require a special provision from the compiler (namely, the compiler could consider than any type extending scala.Dynamic -- and implementing the required lookup methods -- is compatible with any structural typing, and implement the call not via reflection as is normally done, but by calling the corresponding lookup method). 为了完整起见,我必须补充一点, 可以使其按预期工作,但需要编译器提供特殊的规定(即,编译器可以考虑使用任何扩展scala.Dynamic类型,并实现所需的查找方法- -与任何结构化类型兼容,并且不像通常那样通过反射实现调用,而是通过调用相应的lookup方法来实现)。

You are trying to glue together two completely different things. 您正在尝试将两种完全不同的东西粘合在一起。 While structural typing is also sometimes compared to 'duck-typing', its feature is exactly the use of static type information (even if on the use site the byte code will call reflection). 尽管有时也将结构化类型与“鸭式输入”进行比较,但其功能恰恰是静态类型信息的使用(即使在使用现场,字节码也将称为反射)。 Per definition, your dynamic type does not have such static type information. 根据定义,您的动态类型没有此类静态类型信息。 So you will never be able to convince the Scala compiler that your dynamic type has a method that can be statically verified to exist. 因此,您将永远无法说服Scala编译器您的动态类型具有可以静态验证为存在的方法。

The only workaround would be to allow any type in showFullName and use reflection to call fullName (again, I'm not sure if this plays out with a dynamic object). 唯一的解决方法是允许在showFullName使用任何类型,并使用反射来调用fullName (再次,我不确定这是否会与动态对象一起播放)。


On the other hand, Scala will let you do anything with dynamic types, handing the responsibility over to you: 另一方面,Scala将让您使用动态类型做任何事情,并将责任移交给您:

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

println(showFullName(d))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM