What's the purpose of null in X >: Null <: Y?

For example:

abstract type
ClassSymbol >: Null <: Universe.TypeSymbol with Universe.ClassSymbolApi

This was found here. I realize there is a description of what this does, but I can't make sense of it from a syntax standpoint.

What's the purpose of Null? It looks like it might be some kind of default but I only surmise that because I only see this kind of syntax with types, and I think null can be something returns for type without your program breaking. this is an abstract type, but it doesn't have a parameter which you can specify later, so how does this work as an abstract type?

Upvotes: 1

Views: 118

Answers (2)

Rex Kerr
Rex Kerr

Reputation: 167901

Null is a type that specifies that something can be null. It's not a supertype, strictly speaking, because you can't do anything with a null except pass it around and check that, yep, it's still null. In this way it's very much like Nothing, except that you can't even get an instance of a Nothing to pass around.

Now, one could say, "well, any AnyRef could be null", but then how do you think of the instance null itself? null can fill in for pretty much anything, which, as a type, means that it must be a subtype of everything that can be null! And that's what Null is: the subtype of everything that can be Null.

Wait, wait, you say. You can't actually have a subtype of everything--that means that null would have every possible functionality! If you think about it, null does promise every type of functionality that any AnyRef has--but they're all empty promises, and whenever you try to use that functionality you get a NullPointerException instead.

Now, the question is, why make a type >: Null (meaning that null is a valid value for it) instead of <: AnyRef which should imply the same thing?

Well, it turns out that Scala doesn't actually model things that way, to leave open the possibility that you could have an AnyRef which you were absolutely sure could not ever possibly be null. So asking for <: AnyRef ("I am a subclass of AnyRef") doesn't mean the same thing theoretically, even though in practice absolutely-not-null-AnyRefs are not really implemented. (Also, Any would get really awkward if Null was not an explicit type.)

So type Foo >: Null <: Bar just means that you explicitly admit that null can fill in for instances of any possible type of Foo, and thus you can write val foo: Foo = null.

Upvotes: 5

gzm0
gzm0

Reputation: 14842

Consider the following:

trait Foo {
  type A >: Null
  def someA: A = null
}

In the above dummy trait, A is an abstract type member with a type bound. This means: Whatever a subclass defines A to be, Null must be a subtype of it. (The opposite is also possible: A <: Bar).

The main reason for doing is, is to make null be a valid value for A as can be seen in the second line. Without it, scalac would complain at the second line:

found   : Null(null)
required: Foo.this.A

To your question what Null is: It's the type of null and it is a subtype of AnyRef and all of its subtypes.

Upvotes: 3

Related Questions