I am trying to figure out how to create a method that takes a nested object as an argument. For a nested class I can do the following:
scala> class Outer {
| class Inner
| def method(i:Outer#Inner) = { "inner class" }
| }
defined class Outer
However, if I try something like that with an object instead i get an error:
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" }
What should the type of the argument to the method be to accomplish this? Also I want to refer to the type of Inner
object not generalize the argument to say Any
.
Inner
is an object, thus it is not a type, and can't be use as a type. the type of Inner
is Inner.type
. It means, in your example. Unfortunately, each instance of Outer will have it's own Inner object and type Outer#Inner.type
can not be used, since it is not stable. A workaround is to use: this.Inner.type
.
def method(i:this.Inner.type) = { "inner object" }
But it means that you can only pass as a parameter the Inner object of the instance on which you call method
.
A simple example to illustrate what's going on here (in the REPL):
object A
def foo(a : A) = "Does not compile"
def bar(a : A.type) = "Does compile!"
bar(A) // returns "Does compile!"
As Nicholas says, Inner is not a type, so you can't use it as such.
Trying to understand your motivation, I came up with something like this:
class Outer(i : Int) {
object Inner {
def getI : Int = i
}
def foo(x : Inner.type) = x.getI
}
This is a bit pointless, since we would just directly reference Inner - after all, there's only one of it:
class Outer(i : Int) {
object Inner {
def getI : Int = i
}
def foo = Inner.getI
}
I'm guessing that what you want to do is accept an Inner from any instance of Outer. We can check the type of such a thing:
val o = new Outer(1)
:type o.Inner
o.Inner.type
So we might expect to be able to do something like this:
class Outer(i : Int) {
object Inner {
def getI : Int = i
}
def foo(x : Outer#Inner.type) = x.getI
}
This, however, fails to compile. I'm not sure why. Type aliases to the rescue!
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
I'm guessing it's just a restriction of the parser that it's unable to read something of the form A#B.type
. You could potentially submit a bug request.
Each Scala object
has its own type, and there is exactly one value of that type - the object itself. Therefore, the type of a Scala object
is no more useful than the type Unit
.
For example, say you have an object A
and declare a method or function that takes an A.type
parameter:
def foo(arg: A.type) = {}
Since there will always exist exactly one value of type A.type
, we lose no generality by instead referencing it directly inside the method foo
.
If you find yourself wanting to do this, it's more likely that what you really want to abstract over is a trait or base class of the object:
trait Useful { def usefulness: Int }
object A extends Useful { override val usefulness = 42 }
class Foo {
def foo(arg: Useful) = arg.usefulness
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.