1

From documentation.

You can match on the type like so:

sealed trait Device
case class Phone(model: String) extends Device:
  def screenOff = "Turning screen off"

case class Computer(model: String) extends Device:
  def screenSaverOn = "Turning screen saver on..."


def goIdle(device: Device): String = device match
  case p: Phone => p.screenOff
  case c: Computer => c.screenSaverOn

It is a convention to use the first letter of the type as the case identifier (p and c in this case).

Question:

Why do we have a need for separate identifiers p and c here? Why cant we achieve the same with device.screenOff or device.screenSaverOn like in the case of a normal pattern matching?

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
figs_and_nuts
  • 4,870
  • 2
  • 31
  • 56

1 Answers1

4

Both options are valid:

def goIdle(device: Device): String = device match
  case p: Phone    => p.screenOff
  case c: Computer => c.screenSaverOn
def goIdle(device: Device): String = device match
  case p@Phone(_)    => p.screenOff
  case c@Computer(_) => c.screenSaverOn

Imagine that Phone or Computer has many parameters. With the 2nd approach you'll be writing patterns like Phone(_,_,_,....,_), Computer(_,_,_,....,_).

If device has type just Device (not its subtype Phone or Computer) then device.screenOff or device.screenSaverOn doesn't compile.

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
  • Thank you for the answer. Sorry for the laymanesque language - By normal pattern matching I meant all the other pattern matching available on the documentation page apart from matching on type only. Can you please give me an example where ```device has type just Device (not its subtype Phone or Computer) then device.screenOff or device.screenSaverOn doesn't compile.``` How can I have a ```Phone``` or ```Computer``` without creating the classes ```Phone``` and ```Computer``` – figs_and_nuts Mar 08 '23 at 20:22
  • 1
    @figs_and_nuts Probably instead of "creating classes" you meant "instantiating classes". You still can instantiate `Phone` or `Computer` but have variable `device` of type `Device`, e.g. `val device: Device = new Phone("Xiaomi")`, `val device: Device = new Computer("Hewlett-Packard")`, `val device: Device = null`, `val device: Device = ???`, `type T <: Device; val device: T = ???`. In such case `device.screenOff` or `device.screenSaverOn` doesn't compile because the type `Device` itself doesn't have these methods. – Dmytro Mitin Mar 08 '23 at 20:30
  • @figs_and_nuts https://stackoverflow.com/questions/468145/what-is-the-difference-between-type-and-class https://stackoverflow.com/questions/5031640/what-is-the-difference-between-a-class-and-a-type-in-scala-and-java https://typelevel.org/blog/2017/02/13/more-types-than-classes.html – Dmytro Mitin Mar 08 '23 at 20:32
  • @figs_and_nuts https://scastie.scala-lang.org/DmytroMitin/hYmDSS29T1SJjPEYJEDABg `val device: Device = new Phone("Xiaomi")` `value screenOff is not a member of Device` – Dmytro Mitin Mar 08 '23 at 20:35
  • @figs_and_nuts In `val device: Device = new Phone("Xiaomi")` `Phone` is the class of instance (dynamic type, known by JVM at runtime) but `Device` is the static type of variable (known by the compiler at compile time). https://stackoverflow.com/questions/846103/runtime-vs-compile-time – Dmytro Mitin Mar 08 '23 at 20:51
  • @figs_and_nuts surely you can define the variable of type `Phone` or `Computer`. Then the methods will be accessible. Or you can try to move the methods into the parent trait. – Dmytro Mitin Mar 08 '23 at 20:59
  • Thank god I asked this question. Unavailability of ```screenOff``` to ``device``` came as a surprise and all the links you have posted made me realise I am john snow of type and class understanding. I didn't know the rabbit hole went this deep. Going through the links. Thank you, kind sir! – figs_and_nuts Mar 08 '23 at 21:07