CHAPTERS 4 - 6
val acc = new CheckSumAccumulator: you were able to mutate the object
accreferred to, even though
accis a val. What you can't do with
acc, given that it is a
val, not a
var, is reassign a different object to it.
private var sum = 0
Publicis Scala's default access level.
def add(b: Byte) = sum += b: although the Scala compiler will correctly infer the result types of the
add, readers of the code will also need to mentally infer the result types by studying the body of the method. As a result it is often better to explicitly provide the result types of public methods declared in a class even when the compiler would infer it for you.
val s = "hello"; println(s)
classyou use the keyword
newkeyword, you have no way to pass parameters to it. Each singleton object is implemented as an instance of a
synthetic classreferenced from a static variable, so they have the same initialization semantics as Java statics. In particular, a singleton object is initialized the first time some code accesses it.
mainmethod that takes one parameter, an
Array[String], and has a result type of
import ChecksumAccumulator.calculateis an import of the
calculatemethod defined in the
ChecksumAccumulatorobject. This import statement allows you to use the method's simple name in the rest of the file.
scala, as well as the members of a singleton object named
Predef, into every Scala source file.
Predef, which resides in package
scala, contains many useful methods. For example, when you say
printlnin a Scala source file, you're actually invoking
Summer.scalaare scripts, because they end in a definition. A script, by contrast, must end in a result expression. Thus if you try to run
Summer.scalaas a script, the
Scalainterpreter will complain that
Summer.scaladoes not end in a result expression.
scalac ChecksumAccumulator.scala Summer.scalacompiles your source files, but there may be a perceptible delay before the compilation finishes. The reason is that every time the compiler starts up, it spends time scanning the contents of
jarfiles and doing other initial work before it even looks at the fresh source files you submit to it. For this reason, the Scala distribution also includes a Scala compiler daemon called
fsc. You use it like this:
fsc ChecksumAccumulator.scala Summer.Scala
fscdaemon, you can do so with
mainmethod, you place the code you would have put in the
mainmethod directly between the curly braces of the singleton object. You can access command-line arguments via an array of strings named
args. That's it. You can compile and run this application just like any other.
0X, it is hexadecimal (base ), and may contain through as well as upper or lowercase digits through .
Float; otherwise it is a
Double. Optionally, a
Doublefloating-point literal can end in
"""). The interior of a raw string may contain any characters whatsoever, including newlines, quotation marks, and special characters, except of course three quotes in a row.
println(s"Hello, $name!")$ Thes
interpolator will evaluate each embedded expression, invoketoString` on each result, and replace the embedded expressions in the literal with those results. For single-variable expressions, you can often just place the variable name after the dollar sign. If the expression includes non-identifier characters, you must place it in curly braces, with the open curly brace immediately following the dollar sign.
finterpolator allows you to attach
printf-style formatting instructions to embedded expressions.
indexOfmethod searches the string for the first occurrence of the specified character and returns its index or
-1if it doesn't find the character.
Stringoffers an overloaded
indexOfmethod that takes two parameters, the character for which to search and an index at which to start. [...] Whenever you call a method that takes multiple arguments using operator notation, you have to place those arguments in parentheses.
unary_" prepended to the operator character.
List(1,2,3) == "Hello"
==has been carefully crafted so that you get just the equality comparison you want in most cases. This is accomplished with a very simple rule: First check the left side for
null. If it is not
null, call the
equalsis a method, the precise comparison you get depends on the type of the left-hand argument. Since there is an automatic
nullcheck, you do not have to do the check yourself.
eqand its opposite,
ne, only apply to objects that directly map to Java objects.
a +++ b *** cwill be evaluated
a +++ (b *** c), because the
***method has a higher precedence than the
=), and the operator is not one of the comparison operators
!=, then the precedence of the operator is the same as that of simple assignment (
=). That is, it is lower than the precedence of any other operator.
;character is invoked on its right operand, passing in the left operand. Methods that end in any other character are the other way around: They are invoked on their left operand, passing the right operand. So
a * byields
a ::: byields
class Rational(n: Int, d: Int)The identifiers
din the parentheses after the class name,
Rational, are called class parameters. The Scala compiler will gather up these two class parameters and create a primary constructor that takes the same two parameters.
HashSet, for example, that object may not be found the next time you look into the
toStringwould print out the values of the
Rational's numerator and denominator. You can override the default implementation by adding method
Rational, like this:
override def toString = n + "/" + d
require(d != 0)
requirewill prevent the object from being constructed by throwing an
dare in scope in the code of your
addmethod, you can only access their value on the object on which
addwas invoked. Thus, when you say
add's implementation, the compiler is happy to provide you with the values for these class parameters. But it won't let you say
that.dbecause that does not refer to the
Rationalobject on which
addwas invoked. To access the numerator and denominator on
that, you'll need to make them into fields.
def this(n: Int) = this(n, 1)
this(...)". The invoked constructor is either the primary constructor, or another auxiliary constructor that comes textually before calling constructor. The net effect of this rule is that every constructor invocation in Scala will end up eventually calling the primary constructor of the class. The primary constructor is thus the single point of entry of a class.
$character also counts as a letter; however, it is reserved for identifiers generated by the Scala compiler. Identifiers in user programs should not contain
$characters, even though it will compiler; if they do, this might lead to name clashes with identifiers generated by the Scala compiler.
HashSet. Camel-case names of fields, method parameters, local variables, and functions should start with a lower case letter, for example:
s. Camel-case names of classes and traits should start with an upper case letter, for example:
PI. In Scala, the convention is merely that the first character should be upper case. Thus, constants named in the Java style, such as
X_OFFSET, will work as Scala constants, but the Scala convention is to use camel case for constants, such as
$characters. For instance, the identifier
:->would be represented internally as
$colon$minus$greater. If you ever wanted to access this identifier from Java code, you'd need to use this internal representation.
unary_+used as a method name defines a unary
yieldmethod in Java's
Threadclass. You cannot write
yieldis a reserved word in Scala. However, you can still name the method in back ticks, e.g.,
Rational, it won't be in scope in the interpreter. For now, you'll need to define it directly in the interpreter.