分享

学习scala的那五天__第三天

ABCDer丶Bi 发表于 2017-10-21 15:56:33 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 0 4895
本帖最后由 ABCDer丶Bi 于 2017-10-21 16:06 编辑

3.类、对象、继承、特质
Scala的类与JavaC++的类比起来更简洁,学完之后你会更爱Scala!!!
3.1 类
    3.1.1类的定义
    [mw_shl_code=scala,true]
//在Scala中,类并不用声明为public。
//Scala源文件中可以包含多个类,所有这些类都具有公有可见性。
class Person {
  //用val修饰的变量是只读属性,有getter但没有setter
  //(相当与Java中用final修饰的变量)
  val id = "1024"

  //用var修饰的变量既有getter又有setter
  var age: Int = 24

  //类私有字段,只能在类的内部使用
  private var name: String = "奥巴马"

  //对象私有字段,访问权限更加严格的,Person类的方法只能访问到当前对象的字段
  private[this] val pet = "波"

def sayHi(): Unit ={
    print(name)
  }
}
[/mw_shl_code]
    3.1.2构造器
    注意:主构造器会执行类定义中的所有语句
  [mw_shl_code=scala,true]
/**
  *每个类都有主构造器,主构造器的参数直接放置类名后面,与类交织在一起
  */
class Student(val name: String, val age: Int){
  //主构造器会执行类定义中的所有语句
  println("执行主构造器")

  try {
    println("读取文件")
    throw new IOException("io exception")
  } catch {
    case e: NullPointerException => println("打印异常Exception : " + e)
    case e: IOException => println("打印异常Exception : " + e)
  } finally {
    println("执行finally部分")
  }

  private var gender = "male"

  //用this关键字定义辅助构造器
  def this(name: String, age: Int, gender: String){
    //每个辅助构造器必须以主构造器或其他的辅助构造器的调用开始
    this(name, age)
    println("执行辅助构造器")
    this.gender = gender
  }
}

/**
  *构造器参数可以不带val或var,如果不带val或var的参数至少被一个方法所使用,
  *那么它将会被提升为字段
  */
//在类名后面加private就变成了私有的
class Queen private(val name: String, prop: Array[String], private var age: Int = 18){
  
  println(prop.size)

  //prop被下面的方法使用后,prop就变成了不可变得对象私有字段,等同于private[this] val prop
  //如果没有被方法使用该参数将不被保存为字段,仅仅是一个可以被主构造器中的代码访问的普通参数
  def description = name + " is " + age + " years old with " + prop.toBuffer
}

object Queen{
  def main(args: Array[String]) {
    //私有的构造器,只有在其伴生对象中使用
    val q = new Queen("hatano", Array("蜡烛", "皮鞭"), 20)
    println(q.description())
  }
}
[/mw_shl_code]
3.2 对象
    3.2.1单例对象
    Scala中没有静态方法和静态字段,但是可以使用object这个语法结构来达到同样的目的
    1.存放工具方法和常量
    2.高效共享单个不可变的实例
    3.单例模式
    [mw_shl_code=scala,true]
import scala.collection.mutable.ArrayBuffer

object SingletonDemo {
  def main(args: Array[String]) {
    //单例对象,不需要new,用【类名.方法】调用对象中的方法
    val session = SessionFactory.getSession()
    println(session)
  }
}

object SessionFactory{
  //该部分相当于java中的静态块
  var counts = 5
  val sessions = new ArrayBuffer[Session]()
  while(counts > 0){
    sessions += new Session
    counts -= 1
  }

  //在object中的方法相当于java中的静态方法
  def getSession(): Session ={
    sessions.remove(0)
  }
}

class Session{

}
[/mw_shl_code]
    3.2.2伴生对象
    Scala的类中,与类名相同并且用object修饰的对象叫做伴生对象,类和伴生对象之间可以相互访问私有的方法和属性
    [mw_shl_code=scala,true]
class Dog {
  val id = 1
  private var name = "波"

  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()
  }
}
[/mw_shl_code]
    3.2.3Apply方法
    通常我们会在类的伴生对象中定义apply方法,当遇到类名(参数1,...参数n)apply方法会被调用
    [mw_shl_code=scala,true]
object ApplyDemo {
  def main(args: Array[String]) {
    //调用了Array伴生对象的apply方法
    //def apply(x: Int, xs: Int*): Array[Int]
    //arr1中只有一个元素5
    val arr1 = Array(5)
    println(arr1.toBuffer)

    //new了一个长度为5的array,数组里面包含5个null
    var arr2 = new Array(5)
  }
}
[/mw_shl_code]
    3.2.4应用程序对象
    Scala程序都必须从一个对象的main方法开始,可以通过扩展App特质,不写main方法。
  [mw_shl_code=scala,true]
object AppObjectDemo extends App{
  //不用写main方法
  println("I love you Scala")
}
[/mw_shl_code]
3.3 继承
    3.3.1扩展类
    Scala中扩展类的方式和Java一样都是使用extends关键字
    3.3.2重写方法
    Scala中重写一个非抽象的方法必须使用override修饰符
    3.3.3类型检查和转换

Scala
Java
判断对象是否为C类型的实例
obj.isInstanceOf[C]
obj instanceof C
将对象类型强制转换为C类型
obj.asInstanceOf[C]
(C)obj
获取类型TClass对象
classOf[C]
C.class
    3.3.4超类的构造
    [mw_shl_code=scala,true]
object ClassDemo {
  def main(args: Array[String]) {
    //val h = new Human
    //println(h.fight)
  }
}

trait Flyable{
  def fly(): Unit ={
    println("I can fly")
  }

  def fight(): String
}

abstract class Animal {
  def run(): Int
  val name: String
}

class Human extends Animal with Flyable{

  val name = "a"

  //打印几次"ABC"?
  val t1,t2,(a, b, c) = {
    println("ABC")
    (1,2,3)
  }

  println(a)
  println(t1._1)

  //在Scala中重写一个非抽象方法必须用override修饰
  override def fight(): String = {
    "fight with 棒子"
  }
  //在子类中重写超类的抽象方法时,不需要使用override关键字,写了也可以
  def run(): Int = {
    1
  }
}
[/mw_shl_code]
4.模式匹配和样例类
Scala有一个十分强大的模式匹配机制,可以应用到很多场合:如switch语句、类型检查等。
并且Scala还提供了样例类,对模式匹配进行了优化,可以快速进行匹配
4.1模式匹配
4.1.1匹配字符串
  [mw_shl_code=scala,true]
import scala.util.Random

object CaseDemo01 extends App{
  val arr = Array("YoshizawaAkiho", "YuiHatano", "AoiSola")
  val name = arr(Random.nextInt(arr.length))
  name match {
    case "YoshizawaAkiho" => println("吉泽老师...")
    case "YuiHatano" => println("波多老师...")
    case _ => println("真不知道你们在说什么...")
  }
}
[/mw_shl_code]
  4.1.2匹配类型
  [mw_shl_code=scala,true]
import scala.util.Random

object CaseDemo02 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")
  }
}
[/mw_shl_code]
注意case y: Double if(y >= 0) => ...
模式匹配的时候还可以添加守卫条件。如不符合守卫条件,将掉入case _中
  4.1.3匹配数组元组
       [mw_shl_code=scala,true]
object CaseDemo03 extends App{

  val arr = Array(1, 3, 5)
  arr match {
    case Array(1, x, y) => println(x + " " + y)
    case Array(0) => println("only 0")
    case Array(0, _*) => println("0 ...")
    case _ => println("something else")
  }

  val lst = List(3, -1)
  lst match {
    case 0 :: Nil => println("only 0")
    case x :: y :: Nil => println(s"x: $x y: $y")
    case 0 :: tail => println("0 ...")
    case _ => println("something else")
  }

  val tup = (2, 3, 7)
  tup match {
    case (1, x, y) => println(s"1, $x , $y")
    case (_, z, 5) => println(z)
    case  _ => println("else")
  }
}
[/mw_shl_code]
注意:在Scala中列表要么为空(Nil表示空列表)要么是一个head元素加上一个tail列表。
9 :: List(5, 2)  :: 操作符是将给定的头和尾创建一个新的列表
注意::: 操作符是右结合的,如9 :: 5 :: 2 :: Nil相当于 9 :: (5 :: (2 :: Nil))
4.2样例类
Scala中样例类是一种特殊的类,可用于模式匹配。case class是多例的,后面要跟构造参数,case object是单例的
[mw_shl_code=scala,true]
import scala.util.Random

case class SubmitTask(id: String, name: String)
case class HeartBeat(time: Long)
case object CheckTimeOutTask

object CaseDemo04 extends App{
  val arr = Array(CheckTimeOutTask, HeartBeat(12333), SubmitTask("0001", "task-0001"))

  arr(Random.nextInt(arr.length)) match {
    case SubmitTask(id, name) => {
      println(s"$id, $name")
    }
    case HeartBeat(time) => {
      println(time)
    }
    case CheckTimeOutTask => {
      println("check")
    }
  }
}
[/mw_shl_code]
4.3Option类型
ScalaOption类型样例类用来表示可能存在或也可能不存在的值(Option的子类有SomeNone)Some包装了某个值,None表示没有值
[mw_shl_code=scala,true]
object OptionDemo {
  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
    }
    println(v)
    //更好的方式
    val v1 = map.getOrElse("c", 0)
    println(v1)
  }
}
[/mw_shl_code]
4.4偏函数
被包在花括号内没有match的一组case语句是一个偏函数,它是PartialFunction[A, B]的一个实例,A代表参数类型,B代表返回类型,常用作输入模式匹配
[mw_shl_code=scala,true]
object PartialFuncDemo  {

  def func1: PartialFunction[String, Int] = {
    case "one" => 1
    case "two" => 2
    case _ => -1
  }

  def func2(num: String) : Int = num match {
    case "one" => 1
    case "two" => 2
    case _ => -1
  }

  def main(args: Array[String]) {
    println(func1("one"))
    println(func2("one"))
  }
}
[/mw_shl_code]

没找到任何评论,期待你打破沉寂

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条