【问题标题】:What is the type of a nested object in scalascala中嵌套对象的类型是什么
【发布时间】:2012-03-02 17:14:20
【问题描述】:

我试图弄清楚如何创建一个将嵌套对象作为参数的方法。对于嵌套类,我可以执行以下操作:

scala> class Outer { 
 | class Inner
 | def method(i:Outer#Inner) = { "inner class" }
 | }
defined class Outer

但是,如果我用一个对象尝试类似的操作,我会得到一个错误:

scala> class Outer { 
 | object Inner
 | def method(i:Outer#Inner) = { "inner object" }
 | }
<console>:11: error: type Inner is not a member of Outer
   def method(i:Outer#Inner) = { "inner object" }

方法的参数类型应该是什么来完成这个?另外我想参考Inner 对象的类型,而不是泛化论据说Any

【问题讨论】:

    标签: scala object types nested


    【解决方案1】:

    Inner是一个对象,因此它不是一个类型,不能用作一个类型。 Inner 的类型是 Inner.type。这意味着,在你的例子中。不幸的是,每个 Outer 实例都有自己的 Inner 对象,并且类型 Outer#Inner.type 不能使用,因为它不稳定。一种解决方法是使用:this.Inner.type

     def method(i:this.Inner.type) = { "inner object" }
    

    但这意味着您只能将调用method的实例的Inner对象作为参数传递。

    【讨论】:

    • Oups,你也应该使用这个,而不是 Outer。我必须再次阅读依赖类型的解释来解释它。
    • 是的,这行得通!此外,为了在 Outer 类之外定义的方法中使用 Inner,我可以在 Outer 中定义:type InnerType = this.Inner.type 然后我可以定义如下方法:def method(i:Outer#InnerType) = "foo"
    • 可以使用带有类型别名的Outer#Inner.type - 请参阅我的答案。
    【解决方案2】:

    一个简单的例子来说明这里发生了什么(在 REPL 中):

    object A
    def foo(a : A) = "Does not compile"
    def bar(a : A.type) = "Does compile!"
    bar(A) // returns "Does compile!"
    

    正如 Nicholas 所说,Inner 不是一种类型,所以你不能这样使用它。

    试图了解你的动机,我想出了这样的事情:

    class Outer(i : Int) {
      object Inner {
        def getI : Int = i
      }
      def foo(x : Inner.type) = x.getI
    }
    

    这有点没有意义,因为我们只是直接引用 Inner - 毕竟,它只有一个:

    class Outer(i : Int) {
      object Inner {
        def getI : Int = i
      }
      def foo = Inner.getI
    }
    

    我猜你想要做的是接受来自任何外部实例的内部。我们可以检查一下这种东西的类型:

    val o = new Outer(1)
    :type o.Inner
    o.Inner.type
    

    所以我们可能期望能够做这样的事情:

    class Outer(i : Int) {
      object Inner {
        def getI : Int = i
      }
      def foo(x : Outer#Inner.type) = x.getI
    }
    

    但是,这无法编译。我不确定为什么。键入别名以进行救援!

    class Outer(i : Int) {
      type Inner = Inner.type
      object Inner {
        def getI : Int = i
      }
      def foo(x : Outer#Inner) = x.getI
    }
    
    val a = new Outer(1)
    val b = new Outer(2)
    a.foo(b.Inner) //returns 2
    

    我猜这只是解析器的一个限制,它无法读取A#B.type 形式的内容。您可能会提交错误请求。

    【讨论】:

    • type Inner = Inner.type 是否与type Inner = this.Inner.type 相同?还是这两个指的是两种不同的类型?
    • 是的,它们指的是同一个东西。
    【解决方案3】:

    每个 Scala object 都有自己的类型,并且该类型只有一个值——对象本身。因此,Scala object 的类型并不比 Unit 类型有用。

    例如,假设您有一个 object A 并声明一个采用 A.type 参数的方法或函数:

    def foo(arg: A.type) = {}
    

    由于总是存在一个类型为A.type 的值,因此我们直接在方法foo 中引用它不会失去一般性。

    如果您发现自己想要这样做,那么您真正想要抽象的是对象的特征或基类:

    trait Useful { def usefulness: Int }
    object A extends Useful { override val usefulness = 42 }
    class Foo {
      def foo(arg: Useful) = arg.usefulness
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-19
      • 1970-01-01
      • 1970-01-01
      • 2021-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多