`

O'REILLY版《Programming Scala》学习笔记——基础语法部分

阅读更多
Scala 学习笔记
//方法定义格式:
def methodName(param1:String,param2:Stirng):String={
	...
}

返回值类型以及前面的":"可以省略
如果方法体只是一个表达式可以去掉"{}"

Scala必须明确指定类型的场景
1.定义变量的时候必须申明类型,除非这个变量在定义的同时并被赋值
2.所有方法参数必须申明类型
3.以下情况下方法的返回值需要明确定义类型
a.当在方法中明确使用return关键字返回
b.递归方法
c.当一个方法被重载并且当重载的方法调用其他同名方法时需要指定返回类型,如果是调用非同名方法则无需指定返回类型
d.当推断的返回值类型大于你的设想的时候,建议公开的API都指定返回值类型

当一个公共方法为定义范围值类型时,如果改变这个内部方法的实现,这个方法在编译后他的返回值类型可能被修改。
这个情况下如果有已经编译过的客户代码来调用这个方法可能会出错,这时需要重新编译客户端代码。
解决这个问题的最好办法是"公开的API都指定返回值类型"

当方法的返回值类型是自动推断的并且方法体前没有使用"=",Scala将推断这个方法返回类型是Unit
Scala中方法体前有"="被认为是函数定义,如果没有被推断为是一个"procedure"返回类型是Unit
val i=123 //整数类型赋值默认为Int
val l=123L; val ll=123l //如果要赋Long值,需要在添加l或者L,这个和java的规则类似
val b:Byte=127 //变量定义声明类型后可以用合适大小的整数为其赋值
3.14e-5d //Double
3.14e-5D //Double
3.14e-5  //Double,默认
3.14e-5f //Float,要指定为单精度浮点型需要加上f或者F,这个和java的规则类似
3.14e-5F //Float

Tuples 容纳的元素个数1-22
Tuples类型变量实际上是scala.TupleN类的实例
//示例代码 start
def tupleator(x1: Any, x2: Any, x3: Any) = (x1, x2, x3)
val t = tupleator("Hello", 1, 2.3)
println( "Print the whole tuple: " + t )
println( "Print the first item: " + t._1 ) //用t._N得到第N个元素,这里索引从1开始而不是0(索引从1开始是函数式编程的惯例)
println( "Print the second item: " + t._2 )
println( "Print the third item: " + t._3 )
val (t1, t2, t3) = tupleator("World", '!', 0x22)
println( t1 + " " + t2 + " " + t3 )
//示例代码 end
//输出结果:
Print the whole tuple: (Hello,1,2.3)
Print the first item: Hello
Print the second item: 1
Print the third item: 2.3
World ! 34

Some,None是Option的子类,None只是一个对象不是类。
Scala中的空值使用None表示,类似JAVA中的null
Some.get 返回被Some包装的值
None.get 会抛异常 throws a NoSuchElementException
stateCapitals.get("Unknown").getOrElse("Oops2!")  //getOrElse 用法

Scala的类名不用和文件名匹配,包名的定义也不依赖于目录的物理结构
Scala脚本不允许定义包???
Scala中import后的包路径是相对的,只有以"_root_"开始的包路径是绝对路径

Scala基本概念:
1.Scala允许非数字的方法名。+, -, $这些符号都可以作为方法名
2.1 + 2 等同于1 .+(2) 这里1后面必须紧跟一个空格,否则1.被看做是Double。如果方法只有一个参数,可以不用"."和"()"
Scala中方法名、类型名、变量名可以包含ASCII字符,例如字母、数字、下划线(_)、$。单不能包括这些符号:(、)、[、]、{、},这些界定符号也不能包括:`、’、 '、"、.、;、,
Scala一般的定义规则和JAVA类似以一个字母或下划线开头后面可以跟随数字、字母、下划线或者$
$在Scala中有内部含义,不能单独作为定义???

下划线(_)的作用:下划线的存在可以告诉编译器直到下一个空格位置的字符都是定义的一部分。例如val xyz_++= = 1 这里的“xyz_++=”是一个常量的名字,这个表达式的意思就是给常量“xyz_++=”初始化并赋值为1。表达式val xyz++= = 1将编译失败,编译器会看做xyz ++=“xyz”被当成一个变量。
如果下划线后面有操作符(+、-、=等)你不能在后面混合字母和数字,这样是为了防止表达式的含义混淆不清。例如:abc_=123 这个表达式的表示“abc_=123”是一个变量名呢?还是为变量“abc_”赋值为123?
如果标识符以操作符开头,那剩余部分也必须是操作符。
“``”可以用任何字符串来定义标识符。例如val `this is a valid identifier` = "Hello
World!",这里`this is a valid identifier`是一个变量名。有些Scala里的保留字也可以用“``”来转义,例如java.net.Proxy.`type`()

一个无参数的方法定义的时候无需圆括号。
调用一个方法的时候如果不带参数,就不用使用圆括号。例如应该这样List(1, 2, 3).size使用,如果这样调用List(1,2,3).size()就会报错。
However, the length method for java.lang.String does have parentheses in its definition, but Scala lets you write both "hello".length() and "hello".length.
当被调用的方法没有参数或者只有一个参数的时候可以忽略方法名前面的“.”
List(1, 2, 3) size和List(1, 2, 3).size等价

冒号结尾的方法是采用右绑定,其他方法都是左绑定。例如List的::方法
scala> val list = List('b', 'c', 'd')
list: List[Char] = List(b, c, d)
scala> 'a' :: list
res4: List[Char] = List(a, b, c, d)

Scala中if语句可以用来赋值,以下用法类似三元表达式:
val configFile = new java.io.File("~/.myapprc")
val configFilePath = if (configFile.exists()) {
configFile.getAbsolutePath()
} else {
configFile.createNewFile()
configFile.getAbsolutePath()
}

Scala中for的用法:
1.foreach方式:
val dogBreeds = List("Doberman", "Yorkshire Terrier", "Dachshund","Scottish Terrier", "Great Dane", "Portuguese Water Dog")
for (breed <- dogBreeds)
println(breed)

2.Filtering 过滤
for (breed <- dogBreeds
if breed.contains("Terrier")
) println(breed)

for (breed <- dogBreeds
if breed.contains("Terrier");//多个过滤语句用";"分隔
if !breed.startsWith("Yorkshire")
) println(breed)

3.Yielding
//符合过滤条件的元素添加到filteredBreeds 这个list里
val filteredBreeds = for {
breed <- dogBreeds
if breed.contains("Terrier")//for语句使用"{}"包围的时候,多个过滤语句不用";"分隔
if !breed.startsWith("Yorkshire")
} yield breed

for {
breed <- dogBreeds
upcasedBreed = breed.toUpperCase()//upcasedBreed 在for语句里定义的变量(注意:没有使用val)
} println(upcasedBreed)//upcasedBreed这里可以使用前面定义的变量


Scala中没有“break”和“continue”;“&&”、“||”和JAVA中一样是短路操作符号;“==”、“!=”不同于java在Scala中是值比较。
val sundries = List(23, "Hello", 8.5, 'q')
for (sundry <- sundries) {
sundry match {
case i: Int => println("got an Integer: " + i)
case s: String => println("got a String: " + s)
case f: Double => println("got a Double: " + f)
case other => println("got something else: " + other)//other 是匹配其他类型的通配符
}
}

val tupA = ("Good", "Morning!")
val tupB = ("Guten", "Tag!")
for (tup <- List(tupA, tupB)) {
tup match {
  case (thingOne, thingTwo) if thingOne == "Good" =>
    println("A two-tuple starting with 'Good'.")//if做更细粒度的匹配
  case (thingOne, thingTwo) =>
    println("This has two things: " + thingOne + " and " + thingTwo)
}
}

关于模式匹配注意点:如果第一个case条件的匹配范围大于第二个case的范围,那么第二个case将永远不会被到达。这会导致一个编译器错误

//强大的模式匹配,可以直接匹配对象属性
case class Person(name: String, age: Int)
val alice = new Person("Alice", 25)
val bob = new Person("Bob", 32)
val charlie = new Person("Charlie", 32)
for (person <- List(alice, bob, charlie)) {
person match {
case Person("Alice", 25) => println("Hi Alice!")
case Person("Bob", 32) => println("Hi Bob!")
case Person(name, age) =>
println("Who are you, " + age + " year-old person named " + name + "?")
}
}


val BookExtractorRE = """Book: title=([^,]+),\s+authors=(.+)""".r//调用String的r方法将字符串转成正则表达式
val MagazineExtractorRE = """Magazine: title=([^,]+),\s+issue=(.+)""".r
val catalog = List(
"Book: title=Programming Scala, authors=Dean Wampler, Alex Payne",
"Magazine: title=The New Yorker, issue=January 2009",
"Book: title=War and Peace, authors=Leo Tolstoy",
"Magazine: title=The Atlantic, issue=February 2009",
"BadData: text=Who put this here??"
)
for (item <- catalog) {
  item match {
    case BookExtractorRE(title, authors) =>
      println("Book \"" + title + "\", written by " + authors)
    case MagazineExtractorRE(title, issue) =>
      println("Magazine \"" + title + "\", issue " + issue)
    case entry => println("Unrecognized entry: " + entry)
  }
}


Scala中没有checked exceptions,方法定义的时候也没有throws子句。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics