Scala - how to go resolve "Value is not a member of Nothing" error

mjk picture mjk · Aug 2, 2013 · Viewed 9k times · Source

This example code is based on Atmosphere classes, but if someone could give me some insights into what the error means in general, I think I can figure out any Atmosphere-specific solution...

val bc = BroadcasterFactory.getDefault().lookup(_broadcasterId) 
bc.broadcast(message)

After the first line, bc should contain a handle to an object whose class definition includes the method broadcast() -- in fact, it contains several overloaded variations. However, the compiler chokes on the second line of code with the following: "value broadcast is not a member of Nothing"

Any ideas/suggestions on what would be causing this?

Thanks.

EDIT: signature for [BroadcasterFactor].lookup : abstract Broadcaster lookup(Object id)

Note: 1) that is the signature version that I've used in the example, 2) it is the java Inteface signature - whereas the getDefault() hands back an instantiated object that implements that interface.

Solution: force type cast on value:

val bc: Broadcaster = BroadcasterFactory.getDefault().lookup(_broadcasterId)

Answer

senia picture senia · Aug 2, 2013

Nothing is the type name. It's the subtype of all other types. You can't call methods from Nothing itself, you have to specify exact type ((bc: ExactType).broadcast(message)). Nothing has no instances. Method, that returns Nothing will, actually, never return value. It will throw an exception eventually.

Type inference

Definition of lookup:

abstract public <T extends Broadcaster> T  lookup(Object id);

in scala this definition looks this way:

def lookup[T <: Broadcaster](Object id): T

There is not specified type parameter in lookup method. In this case compiler will infer this type parameter as the most specific type - Nothing:

scala> def test[T](i: Int): T = ???
test: [T](i: Int)T

scala> lazy val x = test(1)
x: Nothing = <lazy>                                                                                                                                            

scala> lazy val x = test[String](1)                                                                                                                            
x: String = <lazy>

You could specify type parameter like this:

val bc = BroadcasterFactory.getDefault().lookup[Broadcaster](_broadcasterId) 

Draft implementation

In development process lookup can be "implemented" like this:

def lookup(...) = ???

??? returns Nothing.

You should specify either result type of lookup method like this: def lookup(...): <TypeHere> = ... or type of bc: val bc: <TypeHere> =.