zoukankan      html  css  js  c++  java
  • Scala-Unit5-Scala面对对象与模式匹配

      Java中的面向对象:万物皆对象。

      我们要封装数据,定义模板等操作,素以我们需要面向对象。

    =========================================================================

    一、Scala中的单例对象

      在java中用static关键字修饰方法或成员变量,作用是可以直接通过"类名."的方式调用方法或变量

      在Scala中没有static关键字,Scala给我们提供了单例对象的模式来实现,关键字是object

    object Person {
      //定义成员变量
      val name:String = "Hunter"
      //定义类方法
      def sleep(str:String):Unit= {
        println(str)
      }
    }
    
    object ScalaDemo{
      def main(args: Array[String]): Unit = {
        print(Person.name)
        Person.sleep("睡得很香")
      }
    }
    

      在Scala中的object是一个单例对象,object中定义的方法和成员变量都是静态的,在其他的单例对象中可以直接通过“类名.”的方式进行调用。

      main方法也只能定义在object中,因为java中main方法为静态方法。

      通过class创建的类中定义的方法和对象不能直接调用,不许构造函数对象后才可调用。

    二、Scala类与构造器的使用

      1.类的定义和使用,例子:

    class Person1 {
      //定义成员变量姓名、年龄
      var name:String = _
      var age:Int = _
      //注释:_的意思是不给定,可以在其他类或单例对象中调用赋值,所以用var定义
    }
    
    //继承App特质,可以不写main方法,类似java的Test/Before
    object Test1 extends App{
      val p  = new Person1
      p.name = "reba"
      p.age = 18
      println(p.name + p.age + "岁")
    }
    

      2.主构造器:写在类名后面的构造器是主构造器 

    class Person2 (name:String,age:Int){
    
    }
    
    object Test2 extends App{
      val p = new Person2("yangmi",24)
      println(p)
      println(p.toString)     //这两行输出的都是地址,原因见辅助构造器
    }
    

      注意:主构造器里的变量没有var,val修饰不能被调用

      3.辅助构造器:定义在类内部的构造器,一个类中可以有多个辅助构造器

    class Person3 (var name:String,age:Int){
      var high:Int = _
      var weight:Int = _
    
      //定义辅助构造器
      def this(name:String,age:Int,high:Int){
        this(name,age)
        this.high = high
      }
    
      //辅助构造器可以定义多个
      def this(name:String,age:Int,high:Int,weight:Int){
        this(name,age)
        this.high = high
        this.weight = weight
      }
    }
    
    object Test3 extends App{
      val p = new Person3("Hunter",34,180,140)
      p.weight = 150
      println(p.name + "身高:" +p.high + ",体重:" + p.weight)
    }
    

      注意:(1)辅助构造器内必须先声明主构造器中的所有变量,在声明自己的变量

         (2)Scala中主构造器中的变量如果没有被val、var修饰的话,是不能被访问的,
             相当于java没有给这个变量get/set方法;
             如果主构造器中的变量被val修饰,相当于提供了java中的get方法,
             如果主构造器中的变量被var修饰,相当于提供了java中的get和set方法。

      4.构造器的访问权限:private

        在主构造器或辅助构造器前添加private关键字修饰,即可限制其访问权限

    //定义私有主构造器
    class Person4 private(var name:String,age:int){
      var high:Int = _
      //定义私有辅助构造器
      private def this(name:String,age:Int,high:Int){
        this(name,age)
        this.high = high
      }
    }
    
    
    object ScalaDemo{
      def mian(args:Array[String]):Unit ={
        val p = new Person4("h",88)
        val p1 = new Person3(name = "r",age =18)
        println(p.name)
      }
    
    }
    

     注意:编译时Idea不报错,运行时才会报错;

        但是编程时如果主构造器不是私有的,定义时会出现变量名的提示(如Person3,而Person4没有提示)

      5.类的访问权限,在类前添加private修饰

      测试:

      //测试封装类如下,[this]会根据情况变化为无、[scala04]父包、[demo]子包

    private[this] class Person5(var name:String,age:Int) {
      var high:Int = _
    
      def this(name:String,age:Int,high:Int){
        this(name,age)
        this.high = high
      }
    }
    

      //测试运行单例对象如下:

    object ScalaDemo  {
      def main(args: Array[String]): Unit = {
        val p = new Person5("h",18,182)
        println(p.name)
      }
    }
    

         1>>封装类在父包,省略this,测试类在父包       √
         2>>封装类在父包,省略this,测试类在子包       √
         3>>封装类在父包,添加this,测试类在子包       √
         4>>封装类在父包,添加this,测试类在父包     √
         5>>封装类在父包,添加demo,测试类在父包    ×
         6>>封装类在父包,添加demo,测试类在子包       ×
         7>>封装类在父包,添加scala04,测试类在子包   √
         8>>封装类在父包,添加scala04,测试类在父包   √
       
         1>>封装类在子包,省略this,测试类在子包      √
         2>>封装类在子包,省略this,测试类在父包      ×
         3>>封装类在子包,添加this,测试类在父包      ×
         4>>封装类在子包,添加this,测试类在子包      √
         5>>封装类在子包,添加Scala04,测试类在子包    √
         6>>封装类在子包,添加Scala04,测试类在父包    √
         7>>封装类在子包,添加demo,测试类在父包     ×
         8>>封装类在子包,添加demo,测试类在子包     √

       总结:(1)private[this]修饰类表示当前包下及其子包都可以访问,[this]可以省略;

          (2)若在子包中定义private类,只能子包访问,如想父包访问,需要在private后添加[父包名]

          (3)若在父包中定义private类,且添加[子包名],则父包与子包都无法访问该类

    三、伴生对象:

      定义:在同一个类文件中,单例对象名与类名相同的两个单例对象和类,称之为伴生对象。

    class Person6 (private var name:String,age:Int){
      var high:Int = _
    
      def this (name:String,age:Int,high:Int){
        this(name,age)
        this.high = high
      }
    }
    
    object Person6{
      def main(args: Array[String]): Unit = {
        val p = new Person6("hunter",30)
        println(p.name)
      }
    }
    

      注意:单例对象可以访问其伴生对象类的私有成员变量和方法,

           但伴生对象他们必须在同一个类文件中。

    四、Scala特质和混入特质

      特质:相当于java中的接口

      混入特质:相当与实现多个接口

    trait Animal {
      //定义未实现方法
      def eat(name:String)
    
      //定义实现的方法
      def sleep(name:String):Unit={
        println(s"$name 在睡觉")
      }
    }
    
    trait Running {
      def how(str:String)
    }
    
    object Pig extends Animal with Running {
      override def eat(name: String): Unit = {
        println(s"$name 在吃鸡")
      }
    
      override def how(str: String): Unit = {
        println(f"$str 在奔跑")
      }
    
      def main(args: Array[String]): Unit = {
        Pig.sleep("reba")
        Pig.eat("wyh")
        Pig.how("hunter")
      }
    }
    

      注意:(1)Scala中没有implement,只有extends

         (2)Idea中ctrl+i与ctrl+o的区别:

            ctrl+i:实现未实现的方法

            ctrl+o:重写已经实现的方法

    五、Scala抽象类

    abstract class AbstractDemo {
      def eat(food:String)
    
      def sleep(how:String):Unit={
        println(s"$how->很香")
      }
    }
    
    object AbstractImpl extends AbstractDemo {
      override def eat(food: String): Unit = {
        println(s"hunter is eating $food")
      }
    
      override def sleep(how: String): Unit ={
        println(s"hunter 睡得$how")
      }
    
      def main(args: Array[String]): Unit = {
        AbstractImpl.eat("大猪蹄子")
        AbstractImpl.sleep("很香")
      }
    }
    

      注意:Scala中可以先继承抽象类在继承特质,但是抽象类必须写在前面!!

    六、模式匹配(match/case)

      以下为三个模式匹配的例子,分别匹配了字符串、数组、元祖三种类型:

    object MatchTest {
      def main(args: Array[String]): Unit = {
        def strMatch(str:String):Unit = str match {
          case "Hunter" => println("很帅?")
          case "reba" => println("真的美")
          case _ => println("what?")
        }
    
        strMatch("Hunter")
        strMatch("hunter")
    
        def ArrayMatch(arr:Any):Unit = arr match {
          case Array(1) => println("只有一个元素的数组")
          case Array(1,2) => println("有两个元素的数组")
        }
    
        ArrayMatch(Array(1))
    
        def tupleMatch(tuple:Any):Unit = tuple match {
          case (1,_) => println("元祖第一个元素为1,第二个元素为任意类型")
          case ("hunter",34) => println("这哥们老帅了")
        }
        tupleMatch(("hunter",34))
      }
    }
    
  • 相关阅读:
    BZOJ 3709: [PA2014]Bohater
    BZOJ 3689: 异或之
    BZOJ 4385: [POI2015]Wilcze doły
    2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017) Solution
    Codeforces Round #522 (Div. 2, based on Technocup 2019 Elimination Round 3) Solution
    BZOJ 4320: ShangHai2006 Homework
    BZOJ 4318: OSU!
    2016-2017 ACM-ICPC CHINA-Final Solution
    BZOJ 5312: 冒险
    Codeforces Round #520 (Div. 2) Solution
  • 原文地址:https://www.cnblogs.com/HelloBigTable/p/10275550.html
Copyright © 2011-2022 走看看