zoukankan      html  css  js  c++  java
  • 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
      }
    }
    
    
  • 相关阅读:
    Linux 管道 管线
    中国网络拓扑图(主干网、地区网、主节点一览表)
    C++中的STL中map用法详解
    Git 丢弃本地修改
    Linux下指定so动态库的加载路径的5种方法!!!
    C++中string append函数的使用与字符串拼接
    C++执行shell命令linux
    Linux动态库.so文件加载搜索路径详解
    FFmpeg打印日志函数分析
    linux C/C++中调用shell命令和运行shell脚本
  • 原文地址:https://www.cnblogs.com/xujunkai/p/14413178.html
Copyright © 2011-2022 走看看