scala中嵌套对象的类型是什么

时间:2012-02-10 07:38:40

标签: scala object types nested

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

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

3 个答案:

答案 0 :(得分:13)

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

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

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

答案 1 :(得分:7)

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

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

正如尼古拉斯所说,内心不是一种类型,所以你不能这样使用它。

试图了解你的动机,我想出了类似的东西:

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

这有点无意义,因为我们只是直接引用内部 - 毕竟,只有一个:

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形式的内容。您可能会提交错误请求。

答案 2 :(得分:1)

每个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
}