val x: Int = 42 var y: String = "mutable" val z = "Scala FTW!" // using type inference def add(x: Int, y: Int): Int = x + y // single expression def add(x: Int, y: Int) { // without =, Unit is returned x + y } def min(x: Int, y: Int): Int = { // last line = return value if (x < y) x else y def min(x: Int, y: Int): Int = if (x < y) x else y def min(x: Int, y: Int): Int = { // but don't forget the else if (x < y) x y // bug! def add(x: Int, y: Int) = x + y // return types can be inferred def add(x: Int, y: Int = 2) = x + y // default y to 2 if omitted val add = (x: Int, y: Int) => x + y // anonymous function add(4, 2) // call as usual // convert an anonymous class (Ordering in this case) to a lambda implicit def functionToOrdering[A](f: (A, A) => Int): Ordering[A] = { new Ordering[A] { def compare(a: A, b: A) = f.apply(a, b) } } def runInThread(task: => Int) { new Thread() { override def run(): Unit = task }.start() } 5 * 10 // same as 5.*(10) "Scala" replace("a", "*") class Customer // create a public class class Customer(name: String) // with primary ctor class Customer private(name: String) // private constructor private class Customer // a private class private class Customer private(name: String) // with private ctor val c = new Customer("Bob") // create an instance // class with primary constructor and auxiliary constructor class Customer(forename: String, surname: String) { def this(surname: String) { this("Unknown", surname) } } case class Customer(name: String) // a case class case class Customer(val name: String) // val is redundant here // no need to use "new" to create a new instance with case classes Customer("Bob") // equality and hash code are free with case classes: new Customer("Bob") == new Customer("Bob") // returns true \ // a singleton instance // when paired with a class, the object becomes a "companion" object object Customer class B extends A // subtype inheritance class C(x: Int) class D(value: Int) extends A(value) // calling the super constructor // overriding methods ("override" needed overriding non-abstract methods) class E { def position: Int = 5 } class F extends E { override position: Int = super.position + 1 } // you can mixin in multiple traits but only one class (A) trait SelfDescribing trait Writable class B extends A with SelfDescribing with Writable class B extends SelfDescribing with A with Writable // compiler failure // name is not a field, it's available to the primary constructor only class Customer(name: String) // name is a public field (getter, no setter created) class Customer(val name: String) // name is a public field (getter and setter created) class Customer(var name: String) // name is a private field (a private getter is generated but no setter) class Customer(private val name: String) // name is private (a private getter and setter is generated) class Customer(private var name: String) customer.name_=("Bob") // you can call the setter method directly customer.name = "Bob" // or use infix notation val list = List(1, 4, 234, 12) // create a list val map = Map(1 -> "a", 2 -> "b") // create a map list.foreach(value => println(value)) list.foreach(println) for (value <- list) println(value) // String interpolation replaces '$' tokens with values s"Customer name: $name USD" // Customer name: Bob // Expression require additional parentheses s"Customer basket value is $(customer.basket.value) USD" // The 'f' prefix is like String.format f"Square of 42 is ${math.sqrt(42)}%1.2f" // Square of 42 is 6.48 "Escaping \"quotes\" is the same as in Java" // triple quotes let you span rows and include quotes unescaped """"vCard": { "id" : "007", "name" : "bond", "address" : "MI5" }""" // The 'raw' string interpolator doesn't escape the usual escape chars raw"a\nb" // a\nb val bob = Customer.apply("Bob") // use as factory methods val bob = Customer("Bob") // no need to call explicitly val array = Array(1, 54, 23, 545, 23) array.apply(0) // apply on array is a "getter" array(0) // result is "1" val array = Array(1, 54, 23, 545, 23) array(0) // result is "1" array.update(0, 34) array(0) // result is "34" array(0) = 55 // = is a shortcut to update array(0) // result is "55" value match { case 'R' => ... // literal match case Customer(name) => ... // constructor match (case classes) case x: Int => ... // type query match (ie instance of) case x: Int if x > 5 => ... // with guard condition case (x, y) => ... // deconstruction using unapply case _ => ... // default case } // same syntax is used with try/catch and exceptions try { // ... } catch { case e: MalformedURLException => println("Bad URL") case e: IOException => println(e.getMessage) }