What is the type of nested object in scala

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 similar with the object, I get an error message:

 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 be the type of argument for the method? I also want to refer to the Inner object type to not generalize the argument to say Any .

+7
source share
3 answers

Inner is an object, so it is not a type and cannot be used as a type. type Inner is equal to Inner.type . That means in your example. Unfortunately, each Outer instance will have its own Inner object, and the Outer#Inner.type cannot be used, since it is unstable. The workaround is to use: this.Inner.type .

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

But this means that you can only pass as an argument the Internal object of the instance on which you call method .

+12
source

A simple example illustrating what happens 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 Nikolai says, Inner is not a type, so you cannot 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 little pointless, as we would just refer to Inner only - after all, only one of them:

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

I assume you want to accept 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 can expect that I can do something like this:

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

This, however, cannot be compiled. I do not know why. Enter aliases to help!

 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 assume this is just a parser restriction that it cannot read something from the form A#B.type . You can send an error request.

+7
source

Each Scala object has its own type, and there is only one value of this type - the object itself. Therefore, the Scala object type is no more useful than the Unit type.

For example, let's say you have object A and declare a method or function that takes the A.type parameter:

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

Since exactly one value of type A.type will always exist, we do not lose generality by referring to it directly inside the foo method.

If you want to do this, most likely the fact that you really want to abstract is a sign 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 } 
0
source

All Articles