Reputation: 5300
I tried to add dynamic functionality to a class implicitly by doing the following:
case class C(map: Map[String, String])
implicit class Enhancer(c: C) extends Dynamic {
def selectDynamic(str: String) = c.map.getOrElse(str, "")
}
val c = C(Map("a" -> "A"))
And this will not compile
val up = c.a
But an explicit call will:
val up = Enhancer(c).a
Why is this?
Upvotes: 4
Views: 176
Reputation: 51271
Yes, this will compile...
val up = Enhancer(c).a //up: String = A
...but then, so will this...
val up = Enhancer(c).wxyz //up: String = ""
If class C
doesn't have a member a
, and class Enhancer
doesn't have a member a
, the compiler isn't going to check if a
is supported dynamically because everything is supported dynamically.
If I were designing a language/compiler, and it came to a choice between allowing a.anything
(because Enhancer
is Dynamic
), or allowing only natively supported members (ignoring dynamics), I think I'd go with the latter.
Upvotes: 2
Reputation: 170919
The rule in the specification is
Selection on Dynamic
If none of the previous conversions applies, and
e
is a prefix of a selectione.x
, ande
's type conforms to classscala.Dynamic
, then the selection is rewritten according to the rules for dynamic member selection.
Conformance doesn't include "can be implicitly converted"; so no, you can't add Dynamic
implicitly. You could propose it for some future version of Scala, but I would be surprised if it's accepted.
Upvotes: 2