Search code examples
scalacompilationatmosphere

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


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)

Solution

  • 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> =.