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
.
Yes (see #4)
Structural typing use reflection in background, so it's slow. reflectiveCalls
import is used to warn user about this problem.
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
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
r
is 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.