1. 程式人生 > >scala的面向物件

scala的面向物件

面向物件
1.物件:用object修飾的語法結構
2.類:用class修飾的
3.類的例項:new 類() 類的例項
4.面向物件的三大特徵
(1)封裝
(2)繼承
(3)多型
5.抽象類
6.Trait(介面)
物件
Object
1.單例的,靜態的,scala中根本沒有static關鍵字,為了彌補scala中沒有static關鍵字,scala中使用object代替
2.Static:object代替了static的功能
3.Object本身,沒有構造方法,但是他可以定義成員變數和成員屬性,不能new
伴生物件
是一類特殊的物件,類和物件相伴而生,物件稱之為類的伴生物件,類稱之為物件的伴生類
伴生的條件
1.object的名稱必須和類的名稱一樣
2.必須在同一個原始檔中,在同一個scala檔案中
特點:可以相互訪問物件的私有成員屬性和方法

class HelloScala {
  private val name = "taotao"
}

object HelloScala {
  def main(args: Array[String]): Unit = {
    val h1: HelloScala = new HelloScala()
    val name: String = h1.name
    println(name)
  }
}
//輸出
taotao

物件上有一個特殊的方法:Apply
Apply有一個功能:建立例項
物件()—>預設呼叫的是該物件中的apply方法

def apply(): ApplyDemo = new ApplyDemo()

//定義一個apply的過載方法
def apply(x: Int, y: Int): Int = {
  x * 10 + y * 10
}

def main(args: Array[String]): Unit = {
  //相當於呼叫了ApplyDemo.apply()方法
  println(ApplyDemo())
  //相當於呼叫了ApplyDemo.apply(10,20)方法
  val result: Int = ApplyDemo(10, 20)
  println("result:" + result)
  val result2: Int = ApplyDemo.apply(10, 20)
  println("result2:" + result2)
  val result3: Int = apply(10, 20)
  println("result3:" + result3)
}

//輸出
[email protected]
result:300 result2:300 result3:300

App
App特質,裡面定義了Main方法,物件extends App後,可以不用寫main

object AppDemo extends  App {
  //繼承了APP以後,就相當有了main方法,可以直接執行
  println("12345")

}

//輸出
12345

成員屬性,成員方法(object中也有成員方法)

class Person {
  //定義一個變數
  //val隱藏了get方法,var隱藏了get和set方法
  val name: String = "taotao"
  //_是佔位符,待指的意思,可以變化
  var age: Int = _

  def speak() = {
    println("你聽過一首哲理的歌麼?")
  }

  //alt+fn+insert
  //重寫toString
  override def toString = s"Person($name, $age)"
}

object Person {
  def sing() = {
    println("這裡的山路十八彎")
  }

  def main(args: Array[String]): Unit = {
    val p: Person = new Person()
    val name: String = p.name
    p.age = 20
    val age: Int = p.age
    println(name + "  " + age)
    //插值法輸出,字串前面加s,用$去引用就ok
    println(s"name=${p.name},age=${p.age}")
    p.speak() //可以呼叫伴生類中的成員方法
    Person.sing()
  }
}
//輸出
taotao  20
name=taotao,age=20
你聽過一首哲理的歌麼?
這裡的山路十八彎

注意:
1.val修飾的變數,只能有get方法
2.Var修飾的變數,可以有get和set方法
3.如果重寫toString,則ALT+Fn+INSERT

構造器
1.scala中的構造器,類似java中的構造器
2.Scala中的構造器分為兩類:主構造器和輔助構造器
3.主構造器只有一個,輔助構造器可以有多個

class Student(val name: String, val age: Int) {
  //無參輔助構造器
  def this() = {
    //輔助構造器的第一行,必須呼叫主構造器,或者其他的輔助構造器
    this("taotao", 20)
  }

  var scc: String = _

  //有參的輔助構造器,賦值語句需要寫在第一行
  def this(name: String, age: Int, scc: String) = {
    this(name, age)
    this.scc = scc
  }

  override def toString = s"Student($scc, $name, $age)"
}

object Student {
  def main(args: Array[String]): Unit = {
    //呼叫類的無參構造器,預設使用主構造器
    val student1: Student = new Student()
    println("主構造器:"+student1)
    val student: Student = new Student("huahua", 19)
    println("輔助構造器:"+student)
    println(s"${student.name},${student.age}")
    val stu: Student = new Student("taotao", 20, "xixi")
    println(stu)
  }
}
//輸出
主構造器:Student(null, taotao, 20)
輔助構造器:Student(null, huahua, 19)
huahua,19
Student(xixi, taotao, 20)

注意:
1.主構造器的作用域,是在他整個類的大括號範圍之內,除了定義的方法,全是他的作用域
2.主構造器只能有一個,和類的定義交織在一起
3.輔助構造器的使用,def this(引數列表),來定義
4.主構造器中的變數,使用val和var來宣告,就是成員屬性,在外部也可以訪問,如果不加修飾符,只能在類的內部使用引數名稱而已
5.輔助構造器的第一行,必須呼叫主構造器或者其他的輔助構造器
6.主構造器的引數必須要賦值
7.輔助構造器的引數不能和主構造器的引數和結構一致

優先使用主構造器
訪問許可權
指的是成員方法和成員屬效能不能在其他訪問的到
成員屬性:
預設的訪問許可權:共有的
方法:普通方法和構造器

class Girls private(val age: Int) {
  //私有的
  //如果類中有私有屬性,不想在其的伴生物件中訪問到,那麼
  //private[this] 如果是這種格式,只有本類中才能訪問
  //還可以在private[包的名字]讓屬性在哪些包以及子包中可以訪問的到
  private val name = "taotao"

  def this() {
    this(11)
  }
}

object Girls {
  //伴生物件可以訪問伴生類私有的屬性和方法,其他類中不可以
  def main(args: Array[String]): Unit = {
    val girls: Girls = new Girls(11)
    val name: String = girls.name
    println(name + " " + girls.age)

  }
}
//輸出
taotao 11

注意:

1.一般情況下,我們根本不會刻意去加private許可權,以後只要知道在哪家就可以了
2.預設的訪問許可權是公有的
3.Private 在當前類,伴生物件中可以訪問,在其他的地方無法訪問
4.Private[this] 只有在當前類中有效,其他地方都無效
5.Private[包名]在指定包的下面都有效

抽象類
Abstract修飾
特點:可以有抽象方法,例項方法,不能new,抽象類有構造器

特質 Trait
Trait:類似於java中的介面,功能更加強大,混入特質:extends和with
特質裡是沒有構造器的

Java中的介面:interface —》implements
多實現
Java中的介面,可以寫實現類
特點,沒有構造器,有抽象方法,非抽象方法
1.子類繼承父類,呼叫extends,如果混入特質,用extends,with
2.當沒有顯示父類時候,第一個必須呼叫extends,其他特質都用with
模式匹配
1.match+一系列的case(條件)=>
2.模式匹配是有返回值的
(1)匹配內容
(2)匹配型別
(3)匹配陣列
(4)匹配元組
(5)匹配list集合
(6)匹配樣例類和樣例物件
(7)匹配option(some,none)
匹配內容:

val arr: Array[String] = Array("taotao", "huahua", "jianjian")
//隨機獲取索引
val num: Int = Random.nextInt(arr.length)
println(num)
arr(num) match {
  case "taotao" => println("哈哈哈")
  case "huahua" => println("嘻嘻嘻")
  case "jianjian" => println("嘿嘿嘿")
  //解決匹配不上的問題
  case _ => println("nomatch")
}
//輸出
0
哈哈哈

匹配型別:

val array: Array[Any] = Array[Any](10, 6.6, "taotao")
val num: Int = Random.nextInt(array.length)
println("抽到第:" + num + 1)
array(num) match {
  //加守衛
  case x: Int if x > 10 => println(x)
  case y: Double => println(y)
  case z: String => println(z)

  //匹配不到的,帶守衛的匹配不上,到這裡
  case _ => println("no match")
}
//輸出
抽到第:11
6.6

匹配陣列:
整體的匹配:

val arr: Array[Int] = Array[Int](1, 3, 4, 5, 6)
arr match {
  case Array(a, b, x, y, z) => println(s"a=${a},b=${b},x=${x},y=${y},z=${z}")
  case Array(1, _*) => println("match")
}
//輸出
a=1,b=3,x=4,y=5,z=6

匹配元組:
要求最大值和最小值一起返回

//接收方式
val (max, min) = getValues(Array(1, 3, 5, 7, 8, 3, 9, 0))
val tp2 = getValues(Array(1, 3, 5, 7, 8, 3, 9, 0))

val tp1 = (tp2._1, tp2._2, true)
println("tp1:"+tp1)
val tp = (max, min, true)
tp match {
  case (x, y, z) => println(s"x=${x},y=${y},z=${z}")
  case (x, _, _) => println(x)
  case _ => println("no match")
}
//輸出
tp1:(9,0,true)
x=9,y=0,z=true

匹配list集合

val list1: List[Int] = List[Int](1, 3, 4)
list1 match {
  case List(x, y, z) => println(s"x=${x},y=${y},z=${z}")
  //  x為頭元素,y為尾元素
  case x :: y => println(s"x=${x},y=${y}")
  //  x::y::Nil這樣是不可以的,因為有Nil的時候為具體元素,少一個z是不可以的
  case x :: y :: z :: Nil => println(s"x=${x},y=${y},z=${z}")
  case _ => println("no match")
}
//輸出
x=1,y=3,z=4

匹配樣例類和樣例物件
1、樣例類:
(1)特殊的類:case class person
(2)樣例物件:case object person
(3)樣例類的特點:
①樣例類,不能new
②Case class 必須有主構造器
③預設實現了,equals,hashcode,toString
④實現序列化特質

scala> case class person(name:String,age:Int)
defined class person

scala> val p1=person("li",27)
p1: person = person(li,27)

scala> val p2=person("li",27)
p2: person = person(li,27)

scala> p1==p2
res0: Boolean = true

樣例類支援模式匹配樣例

匹配option

val map: Map[String, Int] = Map[String, Int]("a" -> 100, "b" -> 200, "c" -> 300)
//取值get
val maybeInt: Option[Int] = map.get("a")
val result: Int = maybeInt match {
  case Some(v) => v
  case None => -1
}
println(result)
//輸出
100

偏函式
Def 方法名稱 partialFunction[輸入引數,返回值型別]={
Case xx=>xx
}
省略match

def meth1(name: String): Int = name match {
  case "taotao" => 100
  case "huahua" => 90
  case _ => -1
}

def pf: PartialFunction[String, Int] = {
  case "taotao" => 100
  case "huahua" => 90
  case _ => -1
}

def pf2: PartialFunction[Any, Int] = {
  case x: Int => x * 10
  case _ => -1
}

def main(args: Array[String]): Unit = {
  println(meth1("taotao"))
  println(pf("taotao"))
  val arr: Array[Any] = Array[Any](1, 2, 4, 5, "error")
  val num: Array[Int] = arr.map(pf2)
  println(num.toList)

  //還有一些具體的方法必須偏函式
  val num1: Array[Int] = arr.collect(pf2)
  println(num1.toList)
}

//輸出
100
100
List(10, 20, 40, 50, -1)
List(10, 20, 40, 50, -1)