1、scala裏面的Trait是接口的意思,java裏面是關鍵詞是interface
//scala的接口
trait Htt {
def Htt (name:String)
}
//java的接口
Interface Htt{
void Ya(String name);
}
2、scala不支持對類進行多繼承,但是支持多重繼承trait,使用with關鍵字即可
類繼承trait後,必須實現其中的抽象方法,實現時不需要使用override關鍵字,相當於java裏面的interface
class Person(var name:String) extends SayHello with MakeFriends {
def sayHello (otherName:String) = println("hello , "+otherName)
override def mkFriends(p: Person): Unit = {
println("hello (MakeFriends) : "+p.name +", i am " +name)
}
}
3、Scala中,如果子類要覆蓋一個父類中的非抽象方法,則必須使用override關鍵字
在子類中覆蓋抽象類的抽象方法時,不需要使用override關鍵字
4、val相當於java裏面的final,var相當於一個變量
5、scala中的unit相當於java中的void
6、scala中的通配符是_,java中的通配符是*
7、scala中沒有static,但是可以用object來達到java中相同的效果,scala中的object可以實現單例對象
8、scala中的變量或函數的類型總是寫在變量或者函數名的後面
9、沒有靜態類型,通過object 定義單例類,main方法就是放在object類型中。如下就是簡單的hello world
object MyMain {
def main(args: Array[String]): Unit = {
println("hello world!")
}
}
10、 語法行後面的分號是可選的,可以省略
11、 Scala中== 等效於Java中的Equal,同時支持引用以及實際內容的比較,Scala純粹的引用比較有新的關鍵詞 eq 和ne
12、當調用無參數時,空括號()可以省略
13、當調用對象的無參數方法時, . 以及() 都可以省略。例如: List(1,2,3).size()寫成 List(1,2,3)size
14、類中的無參函數定義
class Complex(real: Double, imaginary: Double) {
def re = real
def im = imaginary
}
15、數字序列語法to、 until
例如2 to 10,表示會2到10之間的數字,如不希望包括10,則可用 2 until 10
16、 match分支匹配關鍵字,對應於Java中的switch,但是可以支持任意的類型。同時可以返回值。
17、for語法不一樣,有<-的特殊符號,示例如下:
for( a <-List(1,2,3))
println(a)
18、for循環在scala中除了以上常規的循環外,還有多重功能
1) 嵌入 if語句,可以過濾,例如下面例子,過濾出偶數
for( a <-List(1,2,3,4) if a %2 ==0) println(a)
2) 多層嵌套, 無需再添加for, 直接嵌套
3) yield語法,可以產生新的集合
var b = for { a <-List(1,2,3,4) if a%2 == 0} yield a
19、函數定義結構和Java存在較大差異
1) 函數使用def 開頭
2) 返回值的類型是在函數聲明後面
3) 函數參數定義的類型是在變量後面
4) 返回值不需要return,最後一個值就可以做爲返回值。
5) 所有的函數參數都val 不可變類型,不可以修改
6) 函數體 前面有 =
def test(a:String, b:Int):String =
{
var c = b + 1
a + b
}
20、函數字面量以及簡短格式。
1) 函數可以作爲變量
var increase = (x:Int) => x +1
increase(10)
2) 函數字面量的簡單格式 ,例如傳入filter函數中的短格式
List(1,2,3,4).filter(x => x% 2==0)
3)函數字面的佔位符語法_,更簡短格式
List(1,2,3,4).filter(_% 2 ==0)
這些語法形式在Java 8也已經有了類似lambda 形式
21、函數變量以及匿名函數
(a:Int)=> 形式來定義函數變量
object Timer {
def oncePerSecond(callback: () => Unit) {
while (true) { callback(); Thread sleep 1000 }
}
def timeFlies() {
println("time flies like an arrow...")
}
def main(args: Array[String]) {
oncePerSecond(timeFlies)
}
}
還可以通過 () =>xx 直接定義匿名函數
oncePerSecond(() =>println("time flies like an arrow..."))
22、類中 public 在scala中爲默認屬性級別,可以不加
23、泛型的括號爲[] ,而Java中爲<>
例如Array[Int]
24、集合索引使用(),而Java中爲[]
例如 List(1,2,3)(0)
25、 數組爲一個單獨類型Array
26、List在scala中默認爲一個不可變的集合類型
27、以List 爲例介紹特有用法
1)::: 連接多個List
2):: 連接值和List
3)符合條件的奇數 count(s => s % 2 ==0)
4) exists(條件)、 filter(條件)、
5)foreah(遍歷函數)
6) map 轉換
用法非常豐富,詳見的api文檔
7)alist sort (_ < _)
28、有元祖的概念,var a = (2,3)
29、Set、Map默認都爲不可變,可以通過import定義爲可變
mportscala.collection.mutable.Set
30、for循環枚舉和條件過濾:
枚舉:
for (i <- 1 to 4)
println(i)
或:
for (i <- 1 until 4)
println(i)
過濾:
for (i <- 1 to 100 if i% 2==0 )
print(i+ ",")
還可以多個if:
for (i <- 1 to 100
if i %2== 0;
if i %3== 0
)
print(i+ ",")
31、佔位符語法
例如我們寫一個f函數:
val f = (_:Int) +(_:Int)
println(f(2, 3))
佔位符還可以用來設置函數的別名:
val a=f _
這樣a和函數f是等效的,f不用傳入參數,直接加個佔位符就可以了
除了上面的做法,還可以:
val f = (_:Int)+(_:Int)
val b = f(1,_:Int)
println(b(10))
32、scala可以通過“*”來定義函數的可變參數:
object Rational {
def echo(args :String*) =
for(arg<-args) println(arg)
def main(args : Array[ String]){
echo("one")
echo("one", "two")
}
}
使用了“*”的函數,不可以把數組當做變量直接傳入,因爲這樣函數會把數組當做一個變量,需要變成如下形式:
object Rational {
def echo(args:String*) =
for(arg<-args) println(arg)
def main(args : Array[ String]){
val arr=Array("one", "two","three" )
// echo(arr) 這是錯誤的
echo(arr:_*)
}
}
使用“:_*”就是告訴解釋器,將數組的中的元素當做一個個參數傳入
33、import關鍵字
scala的import和java的import存在以下區別,在scala中:
1.可以出現在任何地方。
2.可以指的是(單例類或者正統的)對象或包。
3.可以重命名或者隱藏一些被引用的成員。
用例:
//將Rational這個類引入
import cha06.scala.Rational
//將靜態方法Element.elem引入
import Element.elem
//將obejct Element的所有方法引入
import Element._
除了上訴方法外,import除了可以出現在編譯單元的起始位置之外,還可以出現在任何地方。
例如:
private class LineElement(s:String) extends Element{
//將Rational這個類引入
import cha06.scala.Rational
val rational = new Rational( 2, 5)
//....
}
重命名和隱藏:
//只能訪問ArrayBuffer 的 concat和newBuilder兩個方法,其他方法被隱藏
import scala.collection.mutable.ArrayBuffer.{concat ,newBuilder }
//只能訪問ArrayBuffer 的 concat和newBuilder兩個方法,其他方法被隱藏,並且給 concat加了個別名conc,你可以通過conc訪問concat
import scala.collection.mutable.ArrayBuffer.{concat =>conc,newBuilder}
//可以訪問除了newBuilder 外的所有成員
import scala.collection.mutable.ArrayBuffer.{newBuilder =>_,_}
34、類中的apply方法
這個方法在scala中比較特殊,類中定義了apply的方法後,調用這個方法不需要顯示的寫apply。直接寫"實例名(參數列表)"的形式就好。
例如:
tuple(1)事實上是調用了tuple.apply(1)
List(1,2,3,4)事實上是調用了List(1,2,3,4)
35、在類的主構造器中加入參數的時候,如果沒有寫val或者var,那麼主構造器中的參數默認爲private,在類實例化之後不能被外部訪問,如果加了val或者var表示參數可以被外部訪問,等同於private[this] val。
36、嵌套類:
import scala.collection.mutable.ArrayBuffer
class Network{
class Member(val name:String){
val contacts = new ArrayBuffer[Member]
}
private val members = new ArrayBuffer[Member]
def join(name:String) = {
val m = new Member(name)
members += m
m
}
}
val chatter = new Nework
val myFace = new Network
注意:
在scala中chatter.Member和myFace.Member是兩個不同的類
所以以下語句會報錯
var mym = new chatter.Member("yang");
mym = new myFace.Member("face")
37、scala三引號的作用和python三引號的作用相同
38、String Interpolation (String 插值器)
1.s插值器:
例1:
val name = "James"
println(s"Hello, $name") // Hello, James
例2:
println(s"1 + 1 = ${1 + 1}")
2.f插值器:
val height = 1.9d
val name = "James"
println(f"$name%s is $height%2.2f meters tall") // James is 1.90 meters tall
3.raw插值器:
scala> raw"a\nb"
res1: String = a\nb
scala> s"a\nb"
res0: String =
a
b
39、":"結尾的方法是右結合的:
首先我們要知道,scala的語法中"(1).to(10)"是可以寫成"1 to 10"的。在通常情況寫,這種表達式的寫法是從左到右結合的,除了用":"結尾的方法外。用":"結尾的方法屬於從右到左結合的。例如:List的"::"方法,在List中"::"的定義如下:
def ::[B >: A] (x: B): List[B]
但是我們使用的時候可以這樣:
val newList = "a" :: "b" :: List()
自定義例子:
object Log { def >>:(data:String):Log.type = { println(data); Log } }
"Hadoop" >>: "Spark" >>: Log
40、for - yield語法
for{子句}yield{循環體}
41、Singleton對象:
單例對象使用object定義,普通對象使用class定義
當單例對象與某個類共享同一個名稱時,他被稱作是這個類的伴生對象: companion object。你必須在同一個源文件裏定義類和它的伴生對象。類被稱爲是這個單例對象的伴生類: companion class。類和它的伴生對象可以互相訪問其私有成員。object對象在第一次被調用的時候實例化。
object和class可以在內部再定義class。
new關鍵字不能使用在沒有伴生類的伴生對象上,因爲伴生對象是單例類,在第一使用的時候就會創建。
new關鍵字是用來產生類實例的,單例對象只有一個實例就不需要使用new關鍵字了。
例子:
//互相訪問私有變量的例子:
class Myclass{
private var para = 0 //如果使用private[this]修飾,伴生對象就不能訪問
def param = para
def param_=(newPara:Int){para=newPara}
}
object Myclass{
val myc = new Myclass
def objpara = myc.para
}