We give some examples below to show how structural typing is used in Scala.
Example 1
case class ForInt(x: Int) { def myPrint() = println("Int: " + x) } case class ForDouble(x: Double) { def myPrint() = println("Double: " + x) } case class ForString(x: String) { def myPrint() = println("String: '" + x + "'") } val forInt: ForInt = new ForInt(3) val forString: ForString = new ForString("Hello World") val forDouble: ForDouble = new ForDouble(3.14159) /* * This is like defining a "Printable" interface in Java. With structural typing, * however, a type doesn't have to implement a Printable interface explicitly * in order to be recognized as printable. Scala compiler will check that for you. */ type T = { def myPrint(): Unit } val list: List[T] = List[T](forInt, forString, forDouble) list.foreach(_.myPrint())
Example 2
def using[A <: {def close(): Unit}, B](res: A)(op: A => B): B = try op(res) finally res.close def writeToFile(path: String, data: String): Unit = using(new BufferedWriter(new OutputStreamWriter( new FileOutputStream(path), "UTF-8")))(_.write(data)) def appendToFile(path: String, data: String): Unit = using(new BufferedWriter(new OutputStreamWriter( new FileOutputStream(path, true), "UTF-8")))(_.write(data)) def printToFile(path: String)(op: PrintWriter => Unit): Unit = using(new PrintWriter(new BufferedWriter(new OutputStreamWriter( new FileOutputStream(path), "UTF-8"))))(op)
Technical remarks. In Scala 2.10 or later you should either add
import scala.language.reflectiveCallsto any classes that use structural typing, or add the
-language:reflectiveCalls
Calling methods in structural types is made using reflection, which means it will be much slower than a normal method call using a trait. For that reason, structural types in Scala should generally be avoided. Use them when you need them and in situations where the performance impact won't be too significant. See here for arguments on other points against the usefulness of structural typing in Scala. Another concern of duck typing is that it is not type safe. You can do something similar to duck typing in a type-safe and performant manner is to use type classes. Unfortunately, type classes cannot be realized very well in a JVM language, as Java bytecode is type-erasure. See this paper for a proposal arguably better than reflection to do structural typing in JVM languages.
No comments:
Post a Comment