Last active
March 16, 2017 08:37
-
-
Save phipsgabler/084fa1d84511eb52abf0ea7861658f8d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// TO SEE THE PRINTLN'S, RUN `showExamples` IN THE CONSOLE | |
package object example { | |
def showExamples(): Unit = { | |
// # Basics | |
// > Goal of language: modular, functional, OO (+ Java interop) | |
// > Sophisticated hierarchies, type system, and flexible syntax | |
// # Classes | |
// ## Normal & abstract ones | |
abstract class A {} | |
// This gives `B` a constructor and private field `i` | |
class B(i: Int) extends A {} | |
println(new B(234)) | |
// ## Traits (like interfaces, but better) | |
// can hold abstract and concrete methods, as well as fields | |
trait Foo { | |
val x = 42 | |
} | |
// mixin inheritance: | |
val bla = new B(3) with Foo | |
println(bla.x) | |
// ## Case classes: automatic implementation of boilerplace code | |
// E.g. toString, hashCode, equals, canEqual, getters for members, ... | |
// Provide a "factory constructor", ie. no `new` required: | |
case class Bla(n: Int) | |
println(Bla(10)) | |
// contrary to Java, `==` works if `equals` is implemented: | |
println(Bla(10) == Bla(10)) | |
// ## Objects (like singletons, for static members) | |
object Stuff { | |
val PI = 3.0 | |
} | |
println(Stuff.PI) | |
// ## Everything is an object (Any, Nothing, null) | |
println(implicitly[B <:< A]) | |
println(implicitly[Int <:< Any]) | |
println(implicitly[Bla <:< Any]) | |
println(implicitly[Nothing <:< Int]) | |
// `null` still exists (has type `Null`), but only works for | |
// subtypes of `AnyRef`. It should be avoided as a relict of the JVM. | |
// # Values | |
// As we have seen, `val` is used for constants (can only be set once). | |
// `val`s are like fields in Java, they are initialized once at construction. | |
// (There is also `var` for mutable variables, but that is not needed here) | |
// Scala has local type inference, ie., types don't have to be written down, usually: | |
val t = "bla" | |
// But they can be annotated: | |
val t2: String = "bla" | |
// # `def` and functions | |
// Methods can be defined using `def`, with types ascribed using colons. | |
// Note the equals sign! | |
def fact(n: Int): Int = if (n == 0) 1 else n * fact(n - 1) | |
// There is no need for `return` -- we just deal with pure expressions! | |
// As you can see, `if`s are also expressions. | |
// We can use blocks (with braces), too -- but they are also just expressions: | |
val x = { | |
println("hi") | |
3 | |
} | |
println(x == 3) | |
def fact2(n: Int): Int = { | |
if (n == 0) { | |
1 | |
} else { | |
val previous = fact(n - 1) | |
n * previous | |
} | |
} | |
println(fact(10)) | |
// Of course, stuff can be nested: | |
def makeAdder(a: Int): Int => Int = { | |
def addA(b: Int): Int = a + b | |
return addA | |
} | |
val addFour = makeAdder(4) | |
println(addFour(6)) | |
// This also holds for most other sensible combinations of classes, | |
// methods, and objects. | |
// ## Difference between `val` and `def`: | |
// Speaking in Java terms, `val` corresponds to a field of a class, which | |
// is initialized at construction, or a local variable. | |
// `def`, on the other hand, at class level creates a class method, even | |
// if we leave out the method parameters (then we get something like a | |
// getter). | |
class C { | |
val x = { | |
println("x") | |
10 | |
} | |
def y = { | |
println("y") | |
10 | |
} | |
} | |
println("creating c") | |
val c = new C() | |
println("getting x") | |
println(c.x) | |
println("getting x again") | |
println(c.x) | |
println("getting y") | |
println(c.y) | |
println("getting y again") | |
println(c.y) | |
// We can also do the opposite thing, and assign a function object to | |
// a `val`: | |
val successor: Int => Int = n => n + 1 | |
println(successor(10)) | |
// The difference is that a `def` is a class method at JVM level, | |
// while `successor` is a member of a function object type, | |
// `Function1[Int, Int]`, for which // the notation `Int => Int` is just | |
// syntactic sugar. | |
// Methods are easily convertible into function objects. | |
// While we are at syntactic sugar: methods can have (almost) arbitrary | |
// operator names: | |
case class Blub(m: Int) { | |
def +++(b: Blub): List[Blub] = { | |
val Blub(n) = b | |
List(Blub(m), Blub(n), Blub(m + n)) | |
} | |
} | |
println(Blub(1) +++ Blub(2)) | |
// equal to | |
println(Blub(1).+++(Blub(2))) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment