Scala runs on the JVM and can directly call and be called from Java, but source compatibility was not a goal. Scala has a lot of capabilities not in Java, and to help those new features work more nicely, there are a number of differences between Java and Scala syntax that can make reading Scala code a bit of a challenge for Java programmers when first encountering Scala. This primer attempts to explain those differences. It is aimed at Java programmers, so some details about syntax which are the same as Java are omitted.
This primer is not intended to be a complete tutorial on Scala,
rather it is more of a syntax reference.
For a much better introduction to the language,
you should buy the book
Programming in Scala by Martin Odersky, Lex Spoon and Bill Venners.
Most of these syntax differences can be explained by two of Scala‘s
major goals:
The logic behind some of these syntax rules may at first seem arbitrary, but the rules support each other surprisingly well. Hopefully by the time you finish this primer, you will have no trouble understanding code fragments like this one:
Scala is an integrated object/functional language. In the discussion below, the terms "method" and "function" are used interchangeably.
You can run the Scala interpreter and type in these examples
to get a better feel for how these rules work.
class
and an object
of the same name and want them to
be companions, in which case they must be in the same file.
123.toString()
is valid.
val
or
var
keyword can be converted to a function definition
simply by replacing that keyword with the def
keyword.
The syntax at the calling sites does not change.
scala.xml.Elem
to val x:
@
character.static
keyword. Methods and variables that you would declare static in Java go into an object
rather than a class
in Scala. Objects are singletons.break
or continue
statements. Fortunately, Scala‘s support of a functional programming style reduces the need for these.protected
and private
can include a scope in square brackets, such as private[this]
or protected[MyPackage1.MyPackage2]
. The default access is public
.val
keyword declares an immutable value (a val), similar to the final
keyword in Java. The var
keyword declares a mutable variable.import
statement:
java.util.Date
and java.sql.Date
and be able to use them both without having to type the whole qualified name each time, you could do this:
_
, that symbol will not be imported. This allows importing everything except a specified symbol:
abstract
keyword is only used for abstract classes and traits. To declare an abstract function (def), val, variable (var), or type, you omit the =
character and body of the item.override
modifier must be specified. Overriding a method without using the override
modifier or using the modifier when not overriding a superclass method will result in compilation error.lazy
, implicit
scala.xml.Elem
class. Note that "abc\"def"
is a seven character String with a double quote in the middle, but if abc
is an instance of scala.xml.Elem
, then abc\"def"
is a call passing a three character String to the backslash method, a method that accepts a String argument and returns an instance of scala.xml.NodeSeq
.import
statement or in a case
statement to represent a "don‘t care" value. This is because asterisk is a valid symbol character in Scala.case
statement, that difference is used to disambiguate between a constant value, such as PI
if Math.PI
has been imported (starts with upper case) and a placeholder name being introduced (whose scope is then limited to the body of the case statement).5 * { val a = 1; a + 2 }
is valid and yields the value 15.*^
and +^
, the *^
will have higher precedence. The one exception to this rule is that if the operator ends with an equal sign (=
) and is not one of the standard relational operators, then it will have the same precedence as simple assignment.unary_+
, unary_-
etc.?:
ternary operator in Scala. Instead, you use a standard if/then/else statement:
case
statement to allow selecting one possible code path from many based on a value. A simple switch
statement in Java might look like this:
switch
keyword as in Java, Scala uses a match
expression. The match
keyword comes after the value being matched, unlike the relative positions of the switch
keyword and the value in Java.match
works on all types, not just ints. For example, you can match
on a String variable and have case
statements each with a constant String value.break
statement is required, and execution does not fall through to the next case.match
statements return values. The value of a match
statement is the value of whichever branch was executed.case
expression can include patterns, which allow for more complex matching. Case matching is handled by extractors, which can be implemented by writing an unapply
method in an object.case
pattern can include a variable declaration with a type, in which case the variable is defined with that type and set to the value of the matched data within the body of that case.
@
character before the pattern:
if
followed by a boolean expression:
b
gets set to whatever is inside the body
element if there is only one element there:
_*
to match any sequence:
catch
block of a try/catch statement uses the same syntax as the body of a match
statement:
<-
operator in a generator in a for
expression.For Expressions are also called For Comprehensions.
for
expression consists of the for
keyword, a sequence of specific kinds of elements separated by semicolons or newlines and surrounded by parentheses, and the yield
keyword followed by an expression:
n <- 0 to 6
, which produces multiple values and assigns them to a new val (here n
). The new val name appears to the left of the <-
operator; to the right of that operator is a value which implements the foreach
method to generate a series of values.e = n%2
, which introduces a new value by performing the specified calculation.if e==0
, which filters out the values which do not satisfy that expression.for
expression is the same as the type of the first generator.yield
followed by an expression, you can omit the yield
keyword and use a block of code in place of a single expression.for
statement can always be translated into a series of foreach
, filter
, map
and flatMap
method calls. In that sense, the for
statement is syntactic sugar.apply
method.arr(index)
is converted to arr.apply(index)
.arr(index) = newval
is converted to arr.update(index,newval)
.Array
keyword and with the element type in square brackets, rather than using empty square brackets after a type as is done in Java. For example, an array with space for three Strings would be declared like this:
Tuple2[Int,String]
.Pair
object allows that word to be used instead of Tuple2
for building and matching two element Tuples.Triple
object allows that word to be used instead of Tuple3
for building and matching three element Tuples.(1, 2, "foo")
is a Tuple3[Int,Int,String]
.->
operator, which works on any value: "a" -> 25
is the same as ("a", 25)
. The following expression is true:
Any
to Predef.ArrowAssoc
, which contains the ->
method.tens
and 8 to the new val ones
.
val
to make them immutable instance values (vals), or by var
to make them instance variables.private
or protected
. By default, class parameters using val
or var
are public.private
before the parameter list.trait
is like interface
in Java, but can include implementation code. Classes in Scala don‘t implement
traits, they extend
them same as classes. If a class extends multiple traits, or extends a class plus traits, the keyword with
is used rather than commas as in Java.case
keyword before the class
keyword. This automatically does the equivalent of the following:
val
to all parameters, making them immutable instance values.equals
and hashCode
methods so that instances of that class can safely be used in collections.object
of the same name with an apply
method with the same args as declared for the class, to allow creation of instances without using the new
keyword, and with an unapply
method to allow the class name to be used as an extractor in case
statements.isInstanceOf
method is used to determine if an object is an instance of a specific class:
isInstanceOf
, a value can be cast to a specific type by using the type-parameterized asInstanceOf
method:
case
statement, which simultaneously tests for a type and sets a new value of that type:
isInstanceOf
method can be used to test if an object matches a trait as well as a class. It can also be used to test an instance against a structural definition, which can be used to test if an instance implements a specific method:
classOf[MyClass]
as opposed to MyClass.class
as in Java.Int
and all doubles are of type Double
. (In previous versions of Scala, either upper case Int
or lower case int
was accepted, but convention now is to use only the upper case version, and this may be enforced by the compiler in the future.)name:type
rather than type name
as in Java. This is to allow the type to be omitted in many cases, since Scala does type inference. For example, write n:Int
rather than int n
.[T]
rather than in angle brackets <T>
as in Java. Thus a generic type might be specified as F[A,B,C]
.F[+A,-B]
means F is qualified by a covariant type A and a contravariant type B.T<:U
means type U is an upper bound for T, whereas T>:U
means type U is a lower bound for type T.T<%U
means type U is a view bound for T, which allows for implicit conversion to T and can thus support more actual types.Pair[String,Int]
, can be written in infix notation by placing the higher kinded type name between its two type qualifiers, such as String Pair Int
. This makes more sense if the higher kinded type name happens to use operator characters such as +. Thus when you see a type such as Quantity[M + M2]
, as used in the Quantity class in this file, that is the same as Quantity[+[M,M2]]
, so look for a type called +
that takes two type qualifiers.?
wildcard type.type T
in an existential type specification can be replaced by a more complex expression:
type
keyword. Similar to a typedef in C, the type variable simplifies code when a complicated type is used many times:
this
, but optionally using a different name in place of this
:
Outer#Inner
to refer generically to that inner class. If you had an instance x
of class Outer, you would refer to the specific class Inner in that instance by using x.Inner
, which is a distinct type from the Inner
class within any other instance of Outer
, and a subtype of the generic Outer#Inner
class.Unit
rather than void
as in Java. If a function never returns (such as if it always throws a Throwable) the return type is Nothing
.args
parameter would have the type Array[Any]
within the body of the printf
function.apply
method, foo(bar)
(where foo
is an instance of that class) translates to foo.apply(bar)
.
Foo(bar)
that is most likely a call to the apply
method of object Foo
.apply
method can be overloaded, with different versions having different signatures.unapply
in an object definition is also treated specially: it is invoked as an extractor when the object name is used in a case statement pattern.length()
function on String
can be invoked as "abc".length
rather than "abc".length()
. If the function is a Scala function defined without parentheses, then the function must be called without parentheses."Syntactic sugar" is added syntax to make certain constructs easier or more natural to specify. The step in which the compiler replaces these constructs by their more verbose equivalents is called "desugaring".
Function1[A,B]
, functions with two parameters are of type Function2[A,B,C]
, etc. The last type in the list of parameter types is the return value type, so there is always one more than the number N of parameters. A function with no parameters is an instance of Function0[A]
. The name Function
with no number is equivalent to Function1
.(A,B)=>C
is shorthand ("syntactic sugar") for Function2[A,B,C]
.Function1[A,B]
can be written as (A)=>B
, or as just A=>B
.Function0[A]
(i.e. a function with no parameters) can be written as ()=>A
. This function can be called with or without parentheses (as mentioned in the Function Definition section).=>A
. This function must be called without parentheses. If you are declaring a variable x
of this type, the declaration looks like x: =>A
. This signature is often used for call-by-name parameters.list
):
/:
(which also does a foldLeft
):
/:
operator is equivalent to the foldLeft
method (the List class defines both methods).foldLeft
method (and the equivalent /:
operator method) uses a curried parameter list, with the first parameter list having only one method. This allows us to take advantage of the next step.foldLeft
method takes only one parameter (in the first parameter list), we can invoke it without the dot and parentheses.list
object goes on the right and the 0
argument goes on the left.compose
function with three type parameters A, B and C. The regular function parameters are in parentheses.f
is a function that takes one argument of type B
and returns a value of type C
. The parameter g
is also a function.compose
function, which appears after the colon that follows the parentheses, is a function that takes one argument of type A
and returns a value of type C
.=
character, and is a function which has a parameter a
of type A
and returns the value f(g(a))
.compose
function does NOT execute functions f
and g
, but rather returns a function object which, when invoked, will execute f(g)
on its argument.Updated 2008-10-19: added classOf, added infix type notation.
原文:http://www.cnblogs.com/jvava/p/4621071.html