Hook pattern in Scala
I'm looking for a concise documentation of all hooks in Scala. A hook is any situation in the program flow where the common behavior can be intercepted. Such situations include:
- declaration of classes or traits
- access to methods and fields
- mix-in of threads, inheritance
I'm coming from a Ruby background where, for example, method_missing allows to intercept non-existent method calls.
Are such hooks available at al开发者_如何学Cl in Scala?
Matthias
There is no equivalent of method_missing in Scala 2.8 or earlier. In Scala 2.9 (under development), a Dynamic trait will be added. Unknown method calls to objects declaring the Dynamic trait will be automatically translated by the compiler to instead call invokeDynamic
. The idea is to get some of the power of dynamically typed languages in a safe and sane way, without paying the performance overhead of dynamic typing if unneeded. It also simplifies interoperability issues when calling objects defined in dynamic languages from within Scala.
Other than that, hooking in new behaviour in Scala is largely done either via classic inheritance, or by addiing new functionality to objects via implicit conversions.
No, they aren't. In static languages, aspect-oriented programming can be used for some of the same purposes. See Can I do Aspect Oriented Programming in Scala? But of course, "declaration of classes or traits" and "mix-in of threads, inheritance" are not part of the control flow. If you want to intercept them, you'll need a compiler plugin instead.
Scala tends to encourage the use of closures instead of the type of hooks you're talking about (most of which it can't implement conveniently due to static typing and compilation).
This requires you to know in advance where flexibility in the common behavior may be desired, but is very powerful and easy to use when it's available. For example, suppose you have a method that prints out people's names:
case class Name(first: String, last: String) {
def title = last + ", " + first(0).toUpper + "."
}
trait Familiar extends Name {
override def title = first + " " + last(0).toUpper + "."
}
def listing(names: Array[Name]) = names.foreach(name => println(name.title))
val jd1 = new Name("John","Doe)
listing(Array(jd1)) // Prints Doe, J.
val jd2 = new Name("John","Doe") with Familiar
listing(Array(jd2)) // Prints John D.
but if you're really going to be changing name-printing a lot, you're better off building that in:
case class Name(first: String, last: String) {
def title = last + ", " + first(0).toUpper + "."
}
def listing(names: Array[Name], address: Name => String = _.title) =
names.map(address).foreach(println)
val jd = new Name("John", "Doe")
listing(Array(jd)) // Uses default, so prints Doe, J.
listing(Array(jd), n => n.first + " " + n.last(0).toUpper + ".") // Prints John D.
There is no such thing in Scala.
Or, to put it more precisely, static typing ensure we know what will happen at the time the code is compiled. Any such hook would change the behavior at run time, which would defeat the purpose of static typing.
One can modify the behavior at compile time, through compiler plugins, or even change stuff at class load time, through class loaders.
精彩评论