Fork me on GitHub

scala快速入门03

Scala从入门开始03

1.面向对象:

1.1类的定义

// Stendent.scala
package cn._xjk.myobj
/*
* 类
* */
class Stendent {
  val id = 666
  var age: Int = _
  // 伴生对象可以调用
  private var fv: Double = 99.99
  // 只能在 Stendent 内部使用
  private[this] var pwd = "123456"
  def getpwd(): String = {
    pwd
  }
}


/*
* 静态对象
* 伴生对象:跟类同名,并且在同一个文件中
* */
object Stendent{
  def main(args: Array[String]): Unit = {
    val s1 = new Stendent
    val fv = s1.fv
    println(fv)
//    s1.pwd
  }
}


// StudentTest.scala
package cn._xjk.myobj

object StudentTest {
  def main(args: Array[String]): Unit = {
    val s = new Stendent
    println(s.id)
    s.age = 1000
    println(s.age)
    print(s.getpwd())
  }
}

1.2.构造器

  • 构造器分为主构造器和辅助,辅助构造器是主构造器的拓展,辅助构造器第一行需要调主构造器。
  • 主构造器
package cn._xjk.myobj
// 主构造器:与类交织在一起
class Person(val name:String,var age:Int) {

}

object Person {
  def main(args: Array[String]): Unit = {
    val p = new Person("xiaoming", 20)
    // p.name = "James" // 不可修改,因为式val定义
    p.age = 21 // 可以修改式var 定义
    val age = p.age
    val name = p.name

    println(age)
    println(name)
  }
}

  • 辅助构造器
package cn._xjk.myobj

class Animal {
  var name: String = _
  println(name)
  var age:Int = _
  println(age)
  def this(name:String, age:Int) {
    this()
    this.name = name
    this.age = age
  }

}

object Animal {
  def main(args: Array[String]): Unit = {
    val a = new Animal("cat", 15)
    println(a.age)
  }
}
  • 辅助构造器与主构造器结合
package cn._xjk.myobj

class People(val name:String, var age:Int) {
  // 辅助构造器传递额外参数
  var fv:Double = _
  // 定义辅助构造器,补充主构造器功能
  // 定义辅助构造器一定要用def关键字,并且名字只能叫this
  def this(name:String, age:Int, fv:Double) {
    // 辅助构造器的第一行一定得调用构造器
    this(name,age)
    this.fv = fv
  }
//  // 无参辅助构造器
//  def this() {
//    this()
//  }
}

object People{
  def main(args: Array[String]): Unit = {
    val p = new People("Lucy", 33, 55.5)
    println(p.fv)
  }
}

  • 由上面可以知道,为了让类更加灵活,参数一般定义在辅助构造器中,并定义多个辅助构造器,使类传入的参数多样化。

  • 私有构造器

    • 在主构造器参数列表前面加private 表示私有构造器,访问权限只能是伴生对象。
package cn._xjk.myobj

/*
* 在主构造器参数列表前面加private 表示私有构造器
* */
class Monkey private (val name:String) {

}

object Monkey {
  def main(args: Array[String]): Unit = {
    val m = new Monkey("sun wukong")
  }
}
  • 包权限访问
package cn._xjk.myobj
/*
* private[myobj] 表示在同一个myobj包下才可以调用
* */
private[myobj] class Pig {

}

1.3 scala中静态对象

  • 用object修饰

  • 静态对象:object中定义的方法是静态方法,变量也是静态的。

  • 伴生对象:跟类同名,并且在同一个文件中,类和伴生对象之间可以相互访问私有的方法和属性。

  • 单例对象:在Scala中没有静态方法和静态字段,但是可以使用object这个语法结构来达到同样的目的。在scala直接创建就是单例

    package cn._xjk.myobj
    
    object SessionFactory {
      def main(args: Array[String]): Unit = {
        // 创建一个SessionFactory, 单例
        val f1 = SessionFactory// cn._xjk.myobj.SessionFactory$@28f67ac7
        val f2 = SessionFactory// cn._xjk.myobj.SessionFactory$@28f67ac7
    
        println(f1)
        println(f2)
      }
    }
    
    
  • 伴生对象与类之间私有属性和方法,可以互相使用

package cn._xjk.myobj

class Cat {
  private def hello(): Unit ={
    println(Cat.gender)
  }
}
object Cat {
  // 伴生对象的私有方法类中也可以使用
  private val gender = "male"

  def main(args: Array[String]): Unit = {
    val c = new Cat()
    println(c.hello())
  }
}

  • 应用
1.存放工具方法和常量
2.高效共享单个不可变实例
3.单例模式

1.4apply方法

  • 通常我们会在类的伴生对象中定义apply方法,当遇到类名(参数1,...参数n)时apply方法会被调用
package cn._xjk.myobj

class ArrayDemo1 {

}


object ArrayDemo1 {

  def apply(): Unit = {
    println("ok")
  }
  def apply(x:Int):Int = {
    x * x
  }
  def apply(y:Double):Double = {
    y * y
  }
  def main(args: Array[String]): Unit = {
    var arr = ArrayDemo1
    println(arr)

    // ArrayDemo1() 是简写其实是调用了ArrayDemo1.apply()
    // ArrayDemo1()
    // ArrayDemo1.apply()
    // 传入参数,会根据参数个数与类型去调用相应的apply方法
    val r = ArrayDemo1(10)
    print(r) // 180
    val r1 = ArrayDemo1(6.0)
    println(r1)// 36.0
  }
}

1.5应用程序对象

  • Scala程序都必须从一个对象的main方法开始,可以通过扩展App特质,不写main方法。
package cn._xjk.myobj
// 通过继承App不用写main方法,直接运行。App类实现main方法
object AppDemo extends  App {
  print("hello world!")
}

1.6继承

  • 一个类中既有未实现方法,又有实现方法就是一个抽象类
package cn._xjk.myobj.ext

abstract class Animals {
  // 未实现的方法
  def eat():Unit
  // 实现的方法
  def run():Unit = {
    println("跑啊跑")
  }
}

1.7多态

  • 多态实现具备三个条件:子类继承父类,方法重写,父类引用指向子类对象或接口指向实现类。(多态与反射密不可分)
package cn._xjk.myobj.ext

class Dog extends Animals {
  // ctrl+i 导入未实现方法
  // 实现未实现方法
  override def eat(): Unit = {
    println("狗吃肉")
  }
  // ctrl+o 导入重写方法
  override def run(): Unit = {
    println("四个腿,疯狂跑")
  }
}
// 伴生对象
object Dog {
  def main(args: Array[String]): Unit = {
    // 1.Dog 继承 Animals
    // 2.方法重写
    // 3.父类引用: 父类指向子类/接口指向实现类
    val m: Animals = new Dog
    m.run()
  }
}

1.8类型检查与强转

*Scala* *Java*
obj.isInstanceOf[C] obj instanceof C
obj.asInstanceOf[C] (C)obj
classOf[C] C.class
 // 强转类型
 val animal = m.asInstanceOf[Animals]
 animal.run()
 // 判断类型
 val flag = m.isInstanceOf[Animals]
 println(flag)
 // 查看类的class
 val cls = classOf[Dog]
 println(cls)

1.9 trait

  • Scala 的trait相当于Java的接口,即trait中可以由没有实现的方法,也可以由实现的方法。
// Fightable接口实现了fight
trait Fightable {
  def fight(): Unit = {
    println("打架")
  }
}

// Flyable 接口定义了 fly 未实现
trait Flyable {
  def fly():Unit
}
  • 实现接口特性
class Dog extends Animals with Flyable with Fightable {
  // ctrl+i 导入未实现方法
  // 实现未实现方法
  override def eat(): Unit = {
    println("狗吃肉")
  }
  // ctrl+o 导入重写方法
  override def run(): Unit = {
    println("四个腿,疯狂跑")
  }

  override def fly(): Unit = {
    println("蹦蹦跳跳")
  }

  override def fight(): Unit = {
    println("用嘴咬人")
  }
}
object Dog {
  def main(args: Array[String]): Unit = {
    // 1.Dog 继承 Animals
    // 2.方法重写
    // 3.父类引用: 父类指向子类/接口指向实现类
    val m: Dog = new Dog
    m.run()
    m.fly()
    m.fight()
  }
}
  • 一个类,无论是继承还是实现接口特性,第一个都是extends, 如果继承某个类,必须extends修饰,并在第一个
class Pig extends Flyable {
  override def fly(): Unit = {
    println("猪在飞")
  }
}
  • 接口特性可以在伴生对象添加, 但是类不可以动态添加:
package cn._xjk.myobj.ext

class Rabbit {

}

object Rabbit {
  def main(args: Array[String]): Unit = {
    // 伴生对象:动态实现接口
    val r = new Rabbit with Flyable{
      override def fly(): Unit = {
        print("兔子在飞...")
      }
    }
    r.fly()

    // 已经实现接口,直接使用
    val r2 = new Rabbit with Fightable
    r2.fight()
  }
}

1.11 模式匹配和样例类

  • Scala有一个十分强大的模式匹配机制,可以应用到很多场合:如switch语句、类型检查等。

    并且Scala还提供了样例类,对模式匹配进行了优化,可以快速进行匹配

  • 字符串匹配

package cn._xjk.cases

import scala.util.Random

object CaseDemo01 extends App {
  val arr = Array("James", "Curry", "Kebe")
  val name = arr(Random.nextInt(arr.length))
  println(name)

  name match {
    case "James" => println("詹姆斯")
    case  "Kebe" => {
      println("科比")
    }
    case _ => println("什么没有听清,再说一次")
  }
}

  • 数据类型匹配
package cn._xjk.cases

object CaseDemo02 extends App {
  val arr = Array("hello", 1, 2.0, CaseDemo02, 2L)
  val elem = arr(2)
  elem match {
    case x: Int => println(s"Int $x")
    case y: Double if (y >= 0)=> println(s"Double $y")
    case z: String => println(s"String $z")
    case CaseDemo02 => {
      println("case demo 2")
    }
    case _ => {
      println("default")
    }
  }
}

  • 集合添加:
scala> arr :+ 6
res7: List[Int] = List(2, 3, 4, 5, 6)

scala> 1 +: arr
res8: List[Int] = List(1, 2, 3, 4, 5)

scala> arr
res9: List[Int] = List(2, 3, 4, 5)
  • 匹配元组和List
package cn._xjk.cases

object CaseDemo3 extends App {
  val lst = List(0,5)
  println(lst.head) // 0
  println(lst.tail)// List(5)
  // 匹配List
  lst match {
    case 0 :: Nil => println("only 0")
    case x :: y :: Nil => println(s"x $x y $y") // x 0 y 5
    case 0 :: a => println(s"0 ... $a")
    case _ => println("something else")
  }

  // 匹配元组
  val tup = (1,3,7)
  tup match {
    case (1, x, y) => println(s"$x $y")// 3 7
    case (_, z, 5) => println(z)
    case _ => println("something else")
  }
}

  • 除了上述case匹配还可以对class和object匹配:
package cn._xjk.cases

import scala.util.Random

// case class 或 case object 效率更高
/*
* case class 可以不用new 已经实现序列化接口 主要用于模式匹配 多实例(每个实例都可以保存自己实例,有状态)
* case object 主要用于模式匹配 已经实现序列化接口 是单例的, 只要new一次即可
* */
case class SubmitTask(id:String, name:String)
case class HeartBeat(time:Long)
case object CheckTimeOutTask

object CaseDemo04 extends App {
  val arr = Array(CheckTimeOutTask, new HeartBeat(1234), HeartBeat(888888), new SubmitTask("1", "James"))
  val a = arr(Random.nextInt(arr.length))

  a match {
    case SubmitTask(id, name) => {
      println(s"id $id   name $name")
  }
    case HeartBeat(time) => {
      println(time)
    }
    case CheckTimeOutTask => {
      println("CheckTimeOutTask")
    }
  }
}

1.12 Option ,Some,None

  • 在Scala中,从Map中取Key对应Value,返回是一个Option,根据key有可能取到对应value,也有可能取不到,取到了就是Some(v), Some中包装了对应的值,Some是多实例的,所以Some是一个case class。取不到就是None,None不用封装数据,None是单例的,不用封装数据。Some和None都继承了Option

  • 示例1:

val map = Map("a" -> 1, "b" -> 2)

// b存在上面的map中,调用get获取Some(v),然后执行map方法
scala> map.get("b").map(_ *10)
res11: Option[Int] = Some(20)
// c不存在上面map中,调用get获取None,不执行后面map方法
scala> map.get("c").map(_ * 10)
res12: Option[Int] = None
  • 示例2:
package cn._xjk.cases

object OptionDemo {
  def main(args: Array[String]): Unit = {
    val map = Map("a" -> 1, "b" -> 2)
    var r = map.getOrElse("a", 0)
    val o = map.get("b")
    println(o)// None
    val v = o match {
      case Some(i) => {
        i
      }
      case None => 0
    }
    println(v)// 0
  }
}

1.13偏函数

  • 被包在花括号内没有match的一组case语句是一个偏函数,它是PartialFunction[A, B]的一个实例,A代表参数类型,B代表返回类型,常用作输入模式匹配
  • 类型是PartialFunction,由case没有match,主要功能是进行模式匹配。
package cn._xjk.cases

object PartialFuncDemo {
  // 第一个参数传入值
  // 第二个参数为返回值
  def func1: PartialFunction[String, Int] = {
    case "one" => {
      println("one case")
      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]): Unit = {
    print(func2("abc"))// -1
  }
}

posted @ 2021-02-18 19:16  是阿凯啊  阅读(43)  评论(0编辑  收藏  举报