1、類(lèi)
1、類(lèi)的定義和訪(fǎng)問(wèn)限制符
/**
* 類(lèi)的定義,變量聲明與訪(fǎng)問(wèn)限制
* 在Scala中,類(lèi)并不用聲明為public。
*Scala源文件中可以包含多個(gè)類(lèi),所有這些類(lèi)都具有公有可見(jiàn)性。
* Created by 12706 on 2017/11/27.
*/
//private[scu]:包可見(jiàn)性scu是包名,除了該包和子包其他包不可見(jiàn)
//Person private表示構(gòu)造器(無(wú)參的主構(gòu)造器)私有化了,除了伴生對(duì)象外其他對(duì)象里面一旦創(chuàng)建運(yùn)行會(huì)出錯(cuò)
private[scu] class Person private {
//val修飾的屬性,外部只能訪(fǎng)問(wèn)該屬性而不能修改(反編譯后能看到只有g(shù)et方法而沒(méi)有set方法)
val id = 110
//var 修飾的屬性,既有g(shù)et方法也有set方法
var name = "小明"
//private修飾的屬性(類(lèi)私有字段)只能在當(dāng)前類(lèi)(以及伴生對(duì)象 object Person)中訪(fǎng)問(wèn)
private val age : Int = 18
//對(duì)象私有字段,訪(fǎng)問(wèn)權(quán)限更加嚴(yán)格的,連伴生對(duì)象都不能訪(fǎng)問(wèn),只能當(dāng)前類(lèi)才行
private[this] val height : Int = 16
//getHeight()當(dāng)然也行
private def getHeight = {
height
}
}
//伴生對(duì)象,類(lèi)和伴生對(duì)象之間可以相互訪(fǎng)問(wèn)私有的方法和屬性
object Person {
def main(args: Array[String]): Unit = {
//創(chuàng)建對(duì)象,當(dāng)然用new Person()也行
val p = new Person
//訪(fǎng)問(wèn)對(duì)象屬性,訪(fǎng)問(wèn)不到height屬性
println("id:" + p.id)
println("姓名:" + p.name)
println("年齡:" + p.age)
//通過(guò)方法獲height屬性
val height = p.getHeight;
println("身高:" + height)
//修改屬性,只能修改到name
p.name = "小雨"
println("姓名:" + p.name)
}
}
class Man {}
object Man {
def main(args: Array[String]): Unit = {
// 運(yùn)行會(huì)出錯(cuò),因?yàn)闃?gòu)造器被私有化了
// val p = new Person
}
}
對(duì)上面的demo進(jìn)行反編譯,java代碼一目了然
public class Person
{
private final int id = 110;
private String name = "小明";
private final int main$java$cn$scu$scala$day02$Person$$age = 18;
private final int height = 16;
public static void main(String[] paramArrayOfString)
{
Person..MODULE$.main(paramArrayOfString);
}
public int id()
{
return this.id;
}
public String name() { return this.name; }
public void name_$eq(String x$1) { this.name = x$1; }
public int main$java$cn$scu$scala$day02$Person$$age() {
return this.main$java$cn$scu$scala$day02$Person$$age;
}
public int main$java$cn$scu$scala$day02$Person$$getHeight()
{
return this.height;
}
}
2、構(gòu)造器
/**
* 每個(gè)類(lèi)都有主構(gòu)造器,主構(gòu)造器的參數(shù)直接放置類(lèi)名后面,與類(lèi)交織在一起
* Created by 12706 on 2017/11/27.
*/
//height : Int 相當(dāng)于private[this] height : int
//反編譯的時(shí)候能看到成員變量有id,name,age
class People(val id : Int, var name : String, height : Int, private var age : Int = 18) {
}
object People {
def main(args: Array[String]): Unit = {
//age有初始值所以創(chuàng)建對(duì)象時(shí)可以不指定
val p = new People(1,"小明",60);
//訪(fǎng)問(wèn)不了height屬性,height為對(duì)象私有字段
println(p.id + " " +p.age + " " +p.name)
val p2 = new People(1,"小明",60,28);
println(p2.id + " " +p2.age + " " +p2.name)
}
}
輸出
1 18 小明
1 28 小明
/**
* 輔助構(gòu)造器的定義
* Created by 12706 on 2017/11/27.
*/
class Student(val id : Int, val name : String) {
println("執(zhí)行主構(gòu)造器!")
//用this關(guān)鍵字定義輔助構(gòu)造器
def this(id : Int, name : String, age : Int){
//每個(gè)輔助構(gòu)造器必須以主構(gòu)造器或其他的輔助構(gòu)造器的調(diào)用開(kāi)始
this(id,name)
println("執(zhí)行輔助構(gòu)造器")
}
}
object Student {
def main(args: Array[String]): Unit = {
val stu = new Student(1,"小明",20)
//同樣還是訪(fǎng)問(wèn)不到age的
println(stu.name)
}
}
/**
* 主構(gòu)造器會(huì)執(zhí)行類(lèi)定義中的所有語(yǔ)句
* Created by 12706 on 2017/11/27.
*/
class Prop {
println("執(zhí)行主構(gòu)造器")
//定義方法
def method(): Unit ={
println("用我來(lái)讀取文件內(nèi)容 !")
}
//讀取外部文件內(nèi)容
try {
//讀取的整個(gè)文件后轉(zhuǎn)為String
val context = Source.fromFile("d://words.txt").mkString
println(context)
}catch {
case e :Exception => e.printStackTrace()
}finally {
println("讀取文件完畢")
}
}
object Prop {
def main(args: Array[String]): Unit = {
val prop = new Prop
println("================")
prop.method
}
}
輸出
執(zhí)行主構(gòu)造器
hello tom
hello jerry
hello tom
hello jerry
hello tom
hello tom
讀取文件完畢
================
用我來(lái)讀取文件內(nèi)容 !
2、對(duì)象
1、單例對(duì)象
在Scala中沒(méi)有靜態(tài)方法和靜態(tài)字段,但是可以使用object這個(gè)語(yǔ)法結(jié)構(gòu)來(lái)達(dá)到同樣的目的
1.存放工具方法和常量
2.高效共享單個(gè)不可變的實(shí)例
3.單例模式
/**
* java中SessionFactory(hibernate或者是mybatis(SqlSessionFactory))的設(shè)計(jì)就是
* 單例的,通過(guò)它來(lái)獲取Session對(duì)象。使用scala來(lái)進(jìn)行簡(jiǎn)單模擬
* Created by 12706 on 2017/11/27.
*/
//下面相當(dāng)于java的靜態(tài)塊
object SessionFactory{
var counts = 5;
val buffer = new ArrayBuffer[Session](5)
while (counts>0) {
//給buffer緩存塞入5個(gè)Sessio對(duì)象
val session = new Session
buffer += session
counts -= 1
}
//獲取session對(duì)象,相當(dāng)于java的靜態(tài)方法
def getSession(): Unit ={
//緩存中取session
buffer.remove(0)
}
def main(args: Array[String]): Unit = {
//單例對(duì)象,不需要new,用【類(lèi)名.方法】調(diào)用對(duì)象中的方法
val session = SessionFactory.getSession
println(session)
}
}
class Session {
}
2、伴生對(duì)象
在Scala的類(lèi)中,與類(lèi)名相同的對(duì)象叫做伴生對(duì)象,類(lèi)和伴生對(duì)象之間可以相互訪(fǎng)問(wèn)私有的方法和屬性
/**
* 伴生對(duì)象與類(lèi)之間私有屬性的訪(fǎng)問(wèn)
* Created by 12706 on 2017/11/27.
*/
class Dog {
private val name : String = "旺財(cái)"
def bark(){
//訪(fǎng)問(wèn)伴生對(duì)象的私有屬性
println(Dog.voice)
}
}
object Dog {
private val voice : String = "wangwang"
def main(args: Array[String]): Unit = {
val dog = new Dog
//訪(fǎng)問(wèn)對(duì)象的私有name屬性
println(dog.name)
dog.bark()
}
}
2、apply方法
/**
* apply方法:通常我們會(huì)在類(lèi)的伴生對(duì)象中定義apply方法,
* 當(dāng)遇到類(lèi)名(參數(shù)1,...參數(shù)n)時(shí)apply方法會(huì)被調(diào)用
* Created by 12706 on 2017/11/27.
*/
class Point {
private var x : Int = 2
println("主構(gòu)造器被調(diào)用")
def this(x : Int){
this()
this.x = x
}
}
object Point {
def apply(): Unit ={
println("apply()方法被調(diào)用")
}
def apply(x : Int, y : Int): Unit = {
println("apply(x : Int, y : Int)方法被調(diào)用")
}
def apply(x : Int): Point = {
println("apply(x : Int)方法被調(diào)用")
new Point(x)
}
def main(args: Array[String]): Unit = {
val p1 = new Point
println("===================")
//注意兩者區(qū)別,調(diào)用apply方法的時(shí)候不會(huì)執(zhí)行主構(gòu)造器方法
val p2 = Point()
val p3 = Point(3,4)
println("===================")
val p4 = Point(3)
println(p4.x)
}
}
輸出
主構(gòu)造器被調(diào)用
===================
apply()方法被調(diào)用
apply(x : Int, y : Int)方法被調(diào)用
===================
apply(x : Int)方法被調(diào)用
主構(gòu)造器被調(diào)用
3
4、應(yīng)用程序?qū)ο?br> Scala程序都必須從一個(gè)對(duì)象的main方法開(kāi)始,可以通過(guò)擴(kuò)展App特質(zhì),不寫(xiě)main方法。
/**
* 應(yīng)用程序?qū)ο?,單例?duì)象(或者伴生對(duì)象)繼承App即可,App中定義了main方法被繼承過(guò)來(lái)了
* 所以AppDemo中不需要寫(xiě)main方法了
* Created by 12706 on 2017/11/27.
*/
object AppDemo extends App{
val arr = Array(1,2,3,4)
println(arr.toBuffer)
}
3、繼承
1、拓展類(lèi)
在Scala中擴(kuò)展類(lèi)的方式和Java一樣都是使用extends關(guān)鍵字,但是并沒(méi)有使用implements來(lái)實(shí)現(xiàn)接口,都是用extends。如果繼承一個(gè)類(lèi)的同時(shí)也實(shí)現(xiàn)了很多接口,那么用extends 父類(lèi) with 接口1 with 接口2 with…
2、方法的重寫(xiě)
方法重寫(xiě)就是子類(lèi)中對(duì)父類(lèi)的方法實(shí)現(xiàn)重寫(xiě)。
java中接口中都是抽象方法,但是scala中可以有實(shí)現(xiàn),而且關(guān)鍵字是trait稱(chēng)為特質(zhì)。但是重寫(xiě)一個(gè)非抽象方法必須使用override關(guān)鍵字。
3、類(lèi)型檢查和轉(zhuǎn)換
obj.isInstanceOf[C](scala中) ,obj instanceof C(java中)。obj是不是C類(lèi)型
obj.asInstanceOf[C](scala中),(C)obj(java中),obj類(lèi)型強(qiáng)轉(zhuǎn)為C類(lèi)型。
classOf[C](scala中),C.class。獲取C類(lèi)型
/**
* Men是Human類(lèi)(繼承類(lèi)),同時(shí)擁有動(dòng)物的行為(實(shí)現(xiàn)接口)
* Created by 12706 on 2017/11/27.
*/
//Human是類(lèi)必須接在extends后面
class Men extends Human with Animall{
def say(): Unit = {
println("大家好,我的名字叫:" + name)
}
//重寫(xiě)父類(lèi)已經(jīng)實(shí)現(xiàn)的方法需要加override關(guān)鍵字,父類(lèi)沒(méi)實(shí)現(xiàn)那么可加可不加
override def getName(): String = {
this.name
}
}
object Men {
def main(args: Array[String]): Unit = {
val man = new Men
man.name = "xiaoming"
man.say()
println(man.getName())
//類(lèi)型檢查
val b = man.isInstanceOf[Animall]
println(b)
}
}
abstract class Human {
var name : String = _
def say()
}
trait Animall {
def getName(): String = {
"monkey"
}
}
輸出
大家好,我的名字叫:xiaoming
xiaoming
true
_ 對(duì)變量進(jìn)行默認(rèn)初始化,比如var i:Int=_