// A simple expression
5 * 2
// A character
'h'
// A string
"Hello"
// An Object object
new Object
// A constant, inferred typing
val message = "Hello"
// A variable, inferred typing
var message = "hello"
// A variable, explicit typing
var message: String = "hello"
// Assigning a new value to that variable
message = "Yo"
// A very simply method that returns a String (inferred)
def foo = "bar"
// The same thing, explicitly typed return type
def foo: String = "bar"
// The same thing, with parentheses
def foo(): String = "bar"
// Method with a parameter
def timesTwo(n: Int) = n * 2
// Conditional expression
if (foo == 2)
42
else
27
// With braces
if (foo == 2) {
42
}
else {
27
}
// Conditionally assign value to variable using conditional as a statement
var foo: Int = 0
if (bar == 36)
foo = 42
else
foo = 27
// Do the same using conditional as expression
var foo: Int = if (bar == 36) 42 else 27
// Do the same, but make foo constant
val foo: Int = if (bar == 36) 42 else 27
// And use type inferencing
val foo = if (bar == 36) 42 else 27
// Now, a method that uses a conditional expression
def foo(bar: Boolean) = if (bar) 42 else 27
// A method that calls an object's method
def len(s: String) = s.length
// The same, with postfix method syntax
def len(s: String) = s length
// A class that extends Object, but does nothing additional
class Foo
// Override the toString method from Object
class Foo {
override def toString = "A Foo object"
}
// A singleton object, with the toString method overriden
object Bar {
override def toString = "A Bar object"
}
// Assigning a Foo object to a constant
val f = new Foo
// Assigning its String representation to a constant
val s = f toString
// Skipping the middle-man
val s = new Foo toString
// With parens to disambiguate the precedence rules
val s = (new Foo) toString
// Another class, with a constructor, and two constant fields
class MyRange(val start: Int, val end: Int)
// A MyRange object
val r = new MyRange(1, 4)
// Assigning its start and end to constants
val s = r.start
val e = r.end
// Using postfix syntax
val s = r start
val e = r end
// Giving it a toString method
class MyRange(val start: Int, val end: Int) {
override def toString = start + ".." + end
}
// Extending the class
class MyExclusiveEndedRange(val start: Int, val end: Int) extends MyRange(start, end) {
override def toString = start + "..." + end
}
// We need a way to iterate over a range. Let's create a simple Iterator trait.
trait IntIterator {
def start
def current: Int
def atEnd: Boolean
def advance
}
// A class which implements this
class MyRangeIterator(val target: MyRange) extends IntIterator {
private var _current = target.start
def start { _current = target.start }
def current = _current
def atEnd = current > target.end
def advance { _current += 1 }
}
// A method for MyRange which gets us one of these
class MyRange(val start: Int, val end: Int) {
override def toString = start + ".." + end
def iterator = new MyRangeIterator(this)
}
// We can use an anonymous class
class MyRange(val start: Int, val end: Int) {
override def toString = start + ".." + end
def iterator = new IntIterator {
private var _current = start
def reset { _current = start }
def current = _current
def atEnd = current > end
def advance { _current = _current + 1 }
}
}
// Now we can loop over and print the range using the Console object's println method
val r = new MyRange(1, 4)
val i = r.iterator
while (!i.atEnd) {
Console.println(i)
i.advance
}
// The !i.atEnd bit looks ugly. Let's provide a hasMore method with a default implementation.
trait IntIterator {
def start
def current: Int
def atEnd: Boolean
def hasMore = !atEnd
def advance
}
// Now, to rewrite the loop.
val r = new MyRange(1, 4)
val i = r.iterator
while (i.hasMore) {
Console.println(i)
i.advance
}
// Now, that IntIterator trait might be better as a generic trait.
trait Iterator[A] {
def start
def current: A
def atEnd: Boolean
def hasMore = !atEnd
def advance
}
// And now...
class MyRange(val start: Int, val end: Int) {
override def toString = start + ".." + end
def iterator = new Iterator[Int] {
private var _current = start
def reset { _current = start }
def current = _current
def atEnd = current > end
def advance { _current = _current + 1 }
}
}
// But MyRange should probably extend some kind of trait to indicate that it has an iterator method.
trait Iterable[A] {
def iterator: Iterator[A]
}
// ...
class MyRange(val start: Int, val end: Int) extends Iterable[Int] {
override def toString = start + ".." + end
def iterator = new Iterator[Int] {
private var _current = start
def reset { _current = start }
def current = _current
def atEnd = current > end
def advance { _current = _current + 1 }
}
}
// A blast from the past.
class MyExclusiveEndedRange(val start: Int, val end: Int) extends MyRange(start, end) {
override def toString = start + "..." + end
override def iterator = new Iterator[Int] {
private var _current = start
def reset { _current = start }
def current = _current
def atEnd = current >= end
def advance { _current = _current + 1 }
}
}
// All together now!
trait Iterator[A] {
def start
def current: A
def atEnd: Boolean
def hasMore = !atEnd
def advance
}
trait Iterable[A] {
def iterator: Iterator[A]
}
class MyRange(val start: Int, val end: Int) extends Iterable[Int] {
override def toString = start + ".." + end
def iterator = new Iterator[Int] {
private var _current = start
def reset { _current = start }
def current = _current
def atEnd = current > end
def advance { _current = _current + 1 }
}
}
class MyExclusiveEndedRange(val start: Int, val end: Int) extends MyRange(start, end) {
override def toString = start + "..." + end
override def iterator = new Iterator[Int] {
private var _current = start
def reset { _current = start }
def current = _current
def atEnd = current >= end
def advance { _current = _current + 1 }
}
} |