1.定义一个类
class Person{ //用val修饰的变量是只读属性,有getter但是没有setter val id ="111" //用var修饰的变量既有getter又有setter var age:Int =18 //类私有字段,只能在类的内部使用,只有伴生对象内可以使用 private var name:String ="aaa" //对象是由字段,访问权限更加严格,只有person类的方法才能访问当前对象的pet字段 private[this]val pet="bbb" }2.构造器
每个类都有主主构造器,主构造器的参数直接放置类名后面,与类交织在一起,主构造器会执行类定义中的所有语句class Person(val name:String){
//主构造器定义的所有语句都会执行 println("执行主构造器")private var age=11
def this(name:String,age:Int){ //每个辅助构造器必须以主构造器或其他的辅助构造器的调用开始 this(name); println("执行辅助构造器") this.age = age } }构造器参数可以不带var或val,如果不带val或var的参数至少被一个方法所使用,那么它将会被提升为字段
//在类名后面加private就变成了私有的 class moon private(val name:String,prop:Array[String],private var age:Int =18){ println(prop.size)) //prop被下面的方法使用,prop就变成了 def da = prop.toBuffer }object sun{
def main(args:Array[String]) { //私有构造器,只能在伴生对象中使用 val q = moon("aa",Array("111","222"),20) println(q.da()) } }3.单例对象
在Scala中没有静态方法和静态字段,但是可以使用object这个语法结构来达到同样的目的
1.存放工具方法和常量 2.高效共享单个不可变的实例 3.单例模式object SingletonDemo {
def main(args: Array[String]) { //单例对象,不需要new,用【类名.方法】调用对象中的方法 val session = SessionFactory.getSession() println(session) } }4.伴生对象
在Scala的类中,与类名相同的对象叫做伴生对象,类和伴生对象之间可以相互访问私有的方法和属性
class Dog {
val id = 1 private var name = "itcast"def printName(): Unit ={
//在Dog类中可以访问伴生对象Dog的私有属性 println( Dog.CONSTANT + name ) } }/**
- 伴生对象 */ object Dog {
//伴生对象中的私有属性
private val CONSTANT = "汪汪汪 : "def main(args: Array[String]) {
val p = new Dog //访问私有的字段name p.name = "123" p.printName() } }5.apply方法
通常我们会在类的伴生对象中定义apply方法,当遇到类名(参数1,...参数n)时apply方法会被调用
val arr1 = Array(5) println(arr1.toBuffer)调用了Array伴生对象的apply方法,arr1中只有一个元素5
6.Scala程序都必须从一个对象的main方法开始,可以通过扩展App特质,不写main方法。
7.继承一个类或实现一个接口,关键字都需要使用extends,继承后再实现需要用关键字with,
8.在Scala中重写一个非抽象的方法必须使用override修饰符
9.类型检查和转换需要使用obj.isInstanceOf[C]
10.Scala有一个十分强大的模式匹配机制,可以应用到很多场合:如switch语句、类型检查等。
并且Scala还提供了样例类,对模式匹配进行了优化,可以快速进行匹配11.匹配模式
object CaseDemo01 extends App{
//val v = if(x >= 5) 1 else if(x < 2) 2.0 else "hello" val arr = Array("hello", 1, 2.0, CaseDemo) val v = arr(Random.nextInt(4)) println(v) v match { case x: Int => println("Int " + x) case y: Double if(y >= 0) => println("Double "+ y) case z: String => println("String " + z) case _ => throw new Exception("not match exception") } } 匹配模式关键字使用match,case进行每种类型的匹配 case y: Double if(y >= 0) => ... 模式匹配的时候还可以添加守卫条件。如不符合守卫条件,将掉入case _中在Scala中列表要么为空(Nil表示空列表)要么是一个head元素加上一个tail列表。
9 :: List(5, 2) :: 操作符是将给定的头和尾创建一个新的列表 注意::: 操作符是右结合的,如9 :: 5 :: 2 :: Nil相当于 9 :: (5 :: (2 :: Nil))12.Option类型
在Scala中Option类型样例类用来表示可能存在或也可能不存在的值(Option的子类有Some和None)。Some包装了某个值,None表示没有值
def main(args: Array[String]) { val map = Map("a" -> 1, "b" -> 2) val v = map.get("b") match { case Some(i) => i case None => 0 }13.偏函数
被包在花括号内没有match的一组case语句是一个偏函数,它是PartialFunction[A, B]的一个实例,A代表参数类型,B代表返回类型,常用作输入模式匹配
def func1: PartialFunction[String, Int] = {
case "one" => 1 case "two" => 2 case _ => -1 }14.高阶函数
定义函数时格式:val 变量名 = (输入参数类型和个数) => 函数实现和返回值类型和个数
“=”表示将函数赋给一个变量 “=>”左面表示输入参数名称、类型和个数,右边表示函数的实现和返回值类型和参数个数15.匿名函数
在Scala中,你不需要给每一个函数命名,没有将函数赋给变量的函数叫做匿名函数
arr.map(_ 2) 其中_ 2就是一个匿名函数16.柯里化
柯里化指的是将原来接受两个参数的方法变成新的接受一个参数的方法的过程
def m(x: Int)= (y: Int) =>xy m: (x: Int)Int => Int 看起来比较奇怪即像方法又像函数,可以理解为一个方法的实现是 (y: Int) =>xy这个函数
调用val func = m(3)后彻底变成了一个函数
func: Int => Int = 相当于将3出入了函数中,val func =(y:Int)=>3*yfunc(5)在调用这个函数并传递第二个参数,得到最终结果
Int=15柯里化一般和隐式转换一起使用
16.隐式转换
隐式转换和隐式参数是Scala中两个非常强大的功能,利用隐式转换和隐式参数,你可以提供优雅的类库,对类库的使用者隐匿掉那些枯燥乏味的细节。
隐式转换函数是指那种以implicit关键字声明的带有单个参数的函数
/隐式的增强File类的方法
class RichFile(val from: File) { def read = Source.fromFile(from.getPath).mkString }object RichFile {
//隐式转换方法 implicit def file2RichFile(from: File) = new RichFile(from) }object MainApp{
def main(args: Array[String]): Unit = { //导入隐式转换 import RichFile._ //import RichFile.file2RichFile println(new File("c://words.txt").read) } }引入的隐式值>(优先级高于)默认值
如果导入的隐式值有多个同时满足参数会报错17.泛型
多重界定符
/* // 表示:A和B为T上界 T <: A with B // 表示:A和B为T下界 T >: A with B // 表示:同时拥有上界和下界,并且A为下界,B为上界,A为B的子类,顺序不能颠倒。 T >: A <: B // 表示:类型变量界定,即同时满足AT这种隐式值和BT这种隐式值 T:A:B // 表示:视图界定,即同时能够满足隐式转换的A和隐式转换的B T <% A <% B */
具体泛型使用可见:
18.Actor编程
Scala中的Actor能够实现并行编程的强大功能,它是基于事件模型的并发机制,Scala是运用消息(message)的发送、接收来实现多线程的。使用Scala能够更容易地实现多线程应用的开发。
在Scala中,我们可以通过复制不可变状态的资源(即对象,Scala中一切都是对象,连函数、方法也是)的一个副本,再基于Actor的消息发送、接收机制进行并行编程
19.Actor方法执行顺序
(1).首先调用start()方法启动Actor
(2).调用start()方法后其act()方法会被执行 (3).向Actor发送消息20.发送消息的方式
! 发送异步消息,没有返回值。
!? 发送同步消息,等待返回值。 !! 发送异步消息,返回值是 Future[Any]。21.
class AppleActor extends Actor {def act(): Unit = {
while (true) { receive { case "start" => println("starting ...") case SyncMsg(id, msg) => { println(id + ",sync " + msg) Thread.sleep(5000) sender ! ReplyMsg(3,"finished") } case AsyncMsg(id, msg) => { println(id + ",async " + msg) Thread.sleep(5000) } } } } }object AppleActor {
def main(args: Array[String]) { val a = new AppleActor a.start() //异步消息 a ! AsyncMsg(1, "hello actor") println("异步消息发送完成") //同步消息 //val content = a.!?(1000, SyncMsg(2, "hello actor")) //println(content) val reply = a !! SyncMsg(2, "hello actor") println(reply.isSet) //println("123") val c = reply.apply() println(reply.isSet) println(c) } } case class SyncMsg(id : Int, msg: String) case class AsyncMsg(id : Int, msg: String) case class ReplyMsg(id : Int, msg: String)receive阻塞(内部阻塞队列),接受消息,
sender 拿到消息的发送者 isSet判断val中有没有值 apply()方法是同步的 react方法复用线程while(true)和loop的效果一样的
22.
读取文件内容source.fromFile(f) f为文件内容