简体   繁体   中英

What is structure match in scala

Few questions regarding structure matching in scala

Question 1) In the following piece of code, am I am able to pass Bird and Plane to takeOff because Bird and Plane structurally match the object r required by take off?

import scala.language.reflectiveCalls 

case class Bird (val name: String) extends Object {
        def fly(height: Int):Unit = {println("bird fly")}
}

case class Plane (val callsign: String) extends Object {
        def fly(height: Int):Unit = {println("plane fly")}
}

def takeoff(
            runway: Int,
      r: { val callsign: String; def fly(height: Int):Unit }) = {
  println(r.callsign + " requests take-off on runway " + runway)
  println(r.callsign + " is clear for take-off")
  r.fly(1000)
}
val bird = new Bird("Polly the parrot"){ val callsign = name }
val a380 = new Plane("TZ-987")
takeoff(42, bird)
takeoff(89, a380)

Question 2) What is reflectiveCalls? I had to import scala.language.reflectiveCalls otherwise I get the warning reflective access of structural type member value callsign should be enabled by making the implicit value scala.language.reflectiveCalls visible.

Question 3) How can I create Bird as follows: val bird = new Bird("Polly the parrot"){ val callsign = name } . Shouldn't it only be val bird = new Bird("Polly the parrot") . How come this compiles.

Question 3.1). Is bird still of type Bird or is it some other type now because I have passed additional {...}

4) What is the type of r in takeOff .

  1. Yes (see #4)

  2. Structural typing use reflection in background, so it's slow. reflectiveCalls import is used to warn user about this problem.

  3. When you add refinement { val callsign = name } you extend you type Bird with extra field callsign , so now its type matches r as it has both callsign and fly

    3.1 The type of bird is both Bird and structural

     val bird: Bird = new Bird("Polly the parrot"){ val callsign = name } val birdRefined: Bird{ val callsign:String } = new Bird("Polly the parrot"){ val callsign = name } val structuralBird: { val callsign: String; def fly(height: Int): Unit } = birdRefined 
  4. Its called Duck typing or structural type in scala.

You may also be interested in this subtyping relations

implicitly[Bird <:< { def fly(height: Int):Unit }]
//implicitly[Bird <:< { val callsign: String; def fly(height: Int):Unit }] -- fails. Not sybtype. 
implicitly[Plane <:< { val callsign: String; def fly(height: Int):Unit }]
implicitly[Bird {val callsign:String} <:< { val callsign: String; def fly(height: Int):Unit }]
r: AnyRef{val callsign: String; def fly(height: Int): Unit}

For example the following assignment would not compile

val r: { val callsign: String; def fly(height: Int): Unit } = Bird("pigeon")

because Bird("pigeon") is missing callsign .

Note the warning from the docs

Structural types are implemented with reflection at runtime, and are inherently less performant than nominal types.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM