Scala not resolving X as Y, even though X extends Y

[See snippet Below] I read that I have a X which is a Piece, and I have a Player that requires a Piece. The player Me attempts to define this Piece with Piece X. Yet the Scala does not recognize X as a piece, rather it sees 'X.type'. What does X.type mean? I'm not exactly sure what my problem is so I'm having a hard time searching.

I don't see how this can be type shadowing [ See Scala really weird Type Mismatch ], since I don't specify another 'Piece', rather I only specify that I require a 'Piece'.

It seems like there is something preventing Scala to resolve X as a Piece.

To try in REPL

trait Piece { val piece: Char }
case class X extends Piece { val piece: Char = 'X' }

trait Player { val piece: Piece }
case class Me extends Player { val piece: Piece = X }

Result

error: type mismatch;
 found   : X.type
 required: Piece
       case class Max extends Player { val piece: Piece = X }

Answers


That is probably because by X you're only describing a class (so it's actually a type), whereas Scala is expecting an object (or instance) of type Piece. You would get the same error by doing this in the first case:

case class X extends Piece { val piece: Char = Char }

As you can see, your version works because you pass a specific character, not a type. If you want your code to work, you probably have to create a new object and pass it in:

case class Me extends Player { val piece: Piece = new X }

EDIT: As the OP noted in the comment below, using X() also works, because as X is a case class it gets an implicit apply() method:

case class Me extends Player { val piece: Piece = X() }

Case classes without parameters are deprecated. Use case class X() and case class Me() instead. That way you will have to create object of X class with X() call, as is described in other answers.

Alternatively you can use case objects:

case object X extends Piece { val piece: Char = 'X' }.

In fact, if you use case object here, your code will start to work:

case class Me extends Player { val piece: Piece = X }  // Works fine

It depends on your requirements though. It is possible that you need multiple instances of X; then case object is not for you.


When you write case class X, you're also creating a companion object X, which has a member apply that lets you say X(). All this is obvious after some experience with Scala.

X.type is the singleton type of the object X. It has nothing to do with "assigning a type", as the other answers put it.

When you say X as a value, it means that object. It is a term (i.e. value), not a type.

To create a new X, everyone writes X(), which is exactly X.apply(), and never new X(). Never? Yeah, pretty much never.

Note that paramless case classes are long since deprecated.


You are assigning the type X to the variable piece, rather than an instance of X.


Need Your Help

For loop not running in method

java android for-loop return switch-statement

For some reason my for loop is not running and I can't seem to figure out why. It keeps skipping straight to the return statement. Thanks.

Tiny Java Web Server and JMX

java jmx java-server tjws

I'm having a little trouble understanding just how to link JMX agent to my TJWS(Tiny java web server)