【Scala 2.1.8入門】Scala入門④モードマッチング及び異常汎用暗黙変換2019_12_3

24928 ワード

Scala入門④モードマッチング及び異常汎用暗黙変換
  • モードマッチング
  • モードマッチング関数式
  • 定数値一致
  • 範囲マッチング/モードガード
  • 用途要約
  • 字面量・値マッチング
  • 変数タイプ一致
  • Array精密整合
  • List精確一致
  • Array/List集合におけるメタセットマッチング
  • オブジェクト/サンプルクラス一致
  • サンプルクラスマッチング
  • 変数受信マッチング
  • forループ変数受信マッチング
  • バイアス関数
  • 暗黙変換
  • 暗黙関数
  • 暗黙クラス
  • 暗黙パラメータ
  • 暗黙解析機構
  • 異常
  • 汎用
  • コヒーレントインバータ
  • 上下限
  • 補足:Java Classオブジェクト取得
  • 汎用マウント
  • 暗黙パラメータ[汎用]は
  • を限定する.
    パターンマッチング
    Java Switch Case構文に似ていますが、Scala Match Caseの機能はより強力で、コード貫通の問題はありません.
    最も重要なことは、パターンマッチング自体が関数であり、通常は「x=>x match{case}」を「」と省略してキーワードのない匿名関数形式であり、Tupleメタグループ形式では「{case(t 1,t 2)=>...」と略記されるcaseを明記しないと、(t 1,t 2)のタイプ推定ができず、1つのメタグループではなく2つのパラメータとして扱われることである.
    モードマッチング関数式
    object Test {
      def main(args: Array[String]): Unit = {
        //    
        List(1,2,3,4).map(x=>x match {
          case 4 => println("Str")
          case x:Int => println("Int")
        })
        //  
        List(1,2,3,4).map({
          case 4 => println("Array")
          case x:Int => println("Int")
        })
      }
    }
    

    定数の一致
    object Scala01_TestMatch {
      /*0.java switch case     “    ”  , Scala   ,  case     
          switch(byte|short|int|char|enum(1.5)|String(1.7){case:break; ...; default:;}*/
    
      //1.Scala    ,Java Switch     IfElse    ,         ,          
      def main(args: Array[String]): Unit = {
        var a = 10
        val b = 20
    
        //    [switch(var)]
        val control = 'd'
        //2.   :     match { case Boolean   (  · ) => {   } ... case _ => {}}
        val result = control match {
          //        ,       
          case ('+') => {a += 1; a+b}
          case '-' => a - b
          //  case    ,     case _   
          case _ => "illegal"
        }
        println(result)
      }
    }
    

    範囲一致/モードガード
    定数値マッチングは、範囲マッチングの特殊な形式であり、範囲マッチングフォーマットを簡略化していることが理解できます.
    object Scala02_TestMatch {
      def main(args: Array[String]): Unit = {
        println(abs(-8))
      }
    
      def abs(num:Int)={
        num match {
          //     ==>     :
          //case    Boolean   (if  ) => block
          case i if i >=0 => i
          case j if j <0 => -j
          case _ => "illegal"
        }
      }
    }
    

    用途要約
    **ポイント:**case順!!現在のcaseを満たすことはできません!!!注意類似マッチング範囲のcaseは範囲が小さい->大きい順に配列されている.
    字面量・値マッチング
    object Scala03_TestMatch {
      def main(args: Array[String]): Unit = {
        println(describe(true))
      }
    
      /**
       *    ·   
       * @param x    ,  ,  ,    
       * @return String
       */
      def describe (x:Any)= x match {
        case 5 => "Int 5"
        case "hello" => "String hello"
        case true => "Boolean True"
        case '+' => "Char +"
        case _ => "illegal"
      }
    }
    

    変数タイプの一致
    特殊:汎用消去
    object Scala04_TestMatch {
      def main(args: Array[String]): Unit = {
        //1.     ,   
        println(describe(1))
        //1.1 Array    ,       Array(),               Array[]  
        println(describe(Array(1,2,3,4,5)))
        println(describe(Array("abc")))
        //2.    , List        ,            ,      
        //   :    
        println(describe(List("a","b","c")))
        /*
        Int
    	List[]
    	Array[Int]
    	Other Type
    	*/
      }
      def describe(x:Any)= x match {
        case a:Int => "Int"
        case b:String => "String"
        case c:List[Double] => "List[]"
        //case c:List[_] => "List[]" //      
        case d:Array[Int] => "Array[Int]"
        case _ => "Other Type"
      }
    }
    

    Array精密整合
    object Scala05_TestMatch {
      def main(args: Array[String]): Unit = {
        for(arr  "0" //error:constructor cannot be instantiated required String
          })*/
          val result = arr match {
            //      0  [1.      ]
            case Array(0) => "0" 
            //   2    [2.    +       ],          x,y
            case Array(x:Int, y:Int) => x + "," + y 
            //   0   [3.        ]
            case Array(0, _*) => " 0     " 
            case _ => "something else"
          }
          println("result = " + result)
        }
      }
    }
    

    List精確マッチング
    方式1:同Array
    object Scala06_TestMatch {
      def main(args: Array[String]): Unit = {
        //(0)  ,       List(88)           ,     .     
        for (list  "0"
            //         List(  ,      '_',   Error:unbound placeholder parameter
            case List(a) => a
            //         List
            case List(x, y) => x + "," + y
            //   0      List  
            case List(0, _*) => "0 ..."
            case _ => "something else" 
            /*
              0
              88
              1,0
              0 ...
              something else
            */
          }
          println(result)
        }
      }
    }
    

    方式2:独自
    object Scala06_TestMatch {
      def main(args: Array[String]): Unit = {
        val list: List[Int] = List(1, 2, 5, 6, 7)
    
        list match {
          //1.'::'   List                 
          case first :: second :: rest => println(first + "-" + second + "-" + rest)
          case _ => println("something else")
        }//pln 1-2-List(5, 6, 7)
    
        list match {
          //2.   ,    ::          List   
          //3.  :           List  ,'::'           
          //4.    ,     List          
          case first :: second :: third :: rest => println(rest)
          case _ => println("something else")
        }//pln List(6, 7)
      }
    }
    

    Array/Listコレクション内のメタグループマッチング
    きそ
    object Scala07_TestMatch {
      def main(args: Array[String]): Unit = {
        for ( tuple  println("0 ...")
            //       2       0   
            case (y,0) => println(s"$y" + " 0")
            //       2   
            case (a,b) => println(s"$a $b")
            case _ => println("something else")
          }
        }
      }
    }
    

    拡張
      def main(args: Array[String]): Unit = {
        //    1:         
    
        //  1 for(tuple println(a)
            //case (a, _*) => println(a) // Case clauses excepted           
            case _ => println("Illegal")
          }
        }// plt a b c Illegal
    
        //  2 for(tuple       ,    
        println("---   2 tuple._1 ---")
        for (tuple  (t._1,t._2))
        // ((,)=>{})   (,)                 ,         ,      
        //  (    t => (t._1,t._2))              
        println(list.map(t => (t._1, t._2 * 2)))
          
        //  2 map{case (word,count)=>(word,count*2)}
        // map{}     (   match)...
        println(
          list.map{
            case (word,count)=>(word,count*2)
          }
        )
    
        //    3.1     ,       (String,(String,count)),  count * 2
        var list1 = List(("a", ("a", 1)), ("b", ("b", 2)), ("c", ("c", 3)))
        println(
          list1.map{
            case (groupkey,(word,count))=>(word,count*2)
          }
        )
      }
    

    オブジェクト/サンプルクラスの一致
    抽出対象の1つの属性は、抽出器がunapply(obj:Obj):Option[T]抽出対象の複数の属性である場合、抽出器がunapply(obj:Obj):Option[(T 1,T 2,T 3...)]抽出対象の可変属性である場合、抽出器がunapplySeq(obj:Obj):Option[Seq[T]]である
    object Scala08_TestMatch {
      def main(args: Array[String]): Unit = {
        // new User() == User() 【apply  】
        val user: User = new  User("zhangsan", 11)
        val result = user match {
          //case User("zhangsan", 11)   unapply()     ,user(    user match{})  unapply    
          //unapply   user   name age      , User("zhangsan", 11)         
          case User("zhangsan", 11) => "yes"
          case _ => "no"
        }
        println(result)
      }
    }
    
    class User(val name: String, val age: Int)
    object User{
    
      def apply(name: String, age: Int): User = new User(name, age)
    
      /**
       * case   .unapply  (   )  Some,         ,    ;     ,  None    。
       * @param user        user match { case User(    ) }
       * @return   Some  (       user   ),        null,   None
       */
      def unapply(user: User): Option[(String, Int)] = {
        if (user == null)
          None
        else
          Some(user.name, user.age)
      }
    }
    

    サンプルクラスマッチング
  • サンプルクラスは依然としてクラスであり、通常のクラスと比較して、自動的に伴生オブジェクトが生成され、apply、unapply、toString、equals、hashCode、copyなどの伴生オブジェクトで自動的に一般的な方法が実装されるだけである.
  • サンプルクラスは、デフォルトでunapplyメソッドが提供されているため、サンプルクラスは、unapplyメソッドを独自に実装することなく、モードマッチングのために最適化されたクラスである.
  • コンストラクタの各パラメータはvalとなります.varとして明示的に宣言されない限り(推奨されません)
  • です.
    //               
    case class User(name: String, age: Int)
    
    object TestMatchUnapply {
        def main(args: Array[String]): Unit = {
            val user: User = User("zhangsan", 11)
            val result = user match {
                case User("zhangsan", 11) => "yes"
                case _ => "no"
            }
    
            println(result)
        }
    }
    

    変数受信照合
    case class Person(name: String, age: Int)
    
    object Scala09_TestMatch {
      def main(args: Array[String]): Unit = {
        case class Person(name: String, age: Int)
    
        //1.          
        val (x, y) = (1, 2)
        println(s"x=$x,y=$y")
    
        //2.          
        val Array(first, second, _*) = Array(1, 7, 2, 9)
        println(s"first=$first,second=$second")
    
        //3.        
        val Person(name, age) = Person("zhangsan", 16)
        println(s"name=$name,age=$age")
      }
    }
    

    forループ変数受信マッチング
    def main(args: Array[String]): Unit = {
    
        val map = Map("A" -> 1, "B" -> 0, "C" -> 3)
    
        //1. Map         , (k,v)         tuple     
        for ((k, v)  " + v) //3 
        }
        println("----------------------")
    
        //1.2  1     ,  value     k-v ,  v  0,  
        for ((k, 0)  " + 0) // B->0
        }
    
        println("----------------------")
        //1.3  1+for     if v == 0         
        for ((k, v) = 1) {
          println(k + " ---> " + v) // A->1   c->33
        }
      }
    
    

    バイアス関数
    バイアス関数も関数の一種であり,バイアス関数により入力パラメータのより正確な検査を容易に行うことができる.
    まとめ:バイアス関数は,集合内の部分データの処理である.
    バイアス関数の定義:
    //  :     List        
    val second: PartialFunction[List[Int], Option[Int]] = {
        case x :: y :: _ => Some(y)
    }
    
    //   
    val second = new PartialFunction[List[Int], Option[Int]] {
        //          
        override def isDefinedAt(list: List[Int]): Boolean = list match {
            case x :: y :: _ => true
            case _ => false
        }
        //      
        override def apply(list: List[Int]): Option[Int] = list match {
            case x :: y :: _ => Some(y)
        }
    }
    
    

    [外部チェーン画像の転送に失敗しました.ソース局には盗難防止チェーンのメカニズムがある可能性があります.画像を保存して直接アップロードすることをお勧めします(img-UohZar 3 E-1575361305616)(iバイアス関数.png)]
    バイアス関数の使用方法:
    def main(args:Array[String]): Unit = {
      val second: PartialFunction[List[Int], Option[Int]] = {
        case x :: y :: _ => Some(y)
      }
      // :       second(List(1,2,3)),       apply  ,    applyOrElse
      second.applyOrElse(List(1,2,3), (_: List[Int]) => None)
    }
    

    バイアス関数の操作:
    //  :  List(1,2,3,4,5,6,"test")  Int       ,      。
    object Scala10_TestPianFunc {
      def main(args: Array[String]): Unit = {
        //  1:map.filter
        println(List(1, 2, 3, 4, 5, 6, "test").map {
          _ match {
            case i: Int => i + 1
            case s: String => s
          }
        }.filter(a => a.isInstanceOf[Int]))
        //  2:PartitionFunction
        //final override def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[List[A], B, That]): That
        println(List(1, 2, 3, 4, 5, 6, "test").collect { case x: Int => x + 1 })
      }
    }
    

    暗黙的変換
    動作原理とその存在意義:
    コンパイラが最初にコンパイルに失敗すると、タイプを変換したり、二次コンパイルを実現したりするなど、コードコンパイルを通過させる方法が現在の環境で検索されます.
    実質:簡略化版のJava装飾設計モデルであり、既存のソースコードを変更できないタイプに新しい方法を追加する.
    暗黙関数
    実質:「構造関数」、外に書かれた構造関数
      :implicit def funcName(){}
      :
    
    object Scala02_TestImplicit {
      //      ,    implicit      
      //  :            (             ,      )
      //  :"    ",         (       )
      implicit def convert(a: Int) = {
        new MyRichInt(a)
      }
    
      def main(args: Array[String]): Unit = {
        // Int   /      MyRichInt   
        //          ,      ,                               
        println(2.myMax(6))
      }
    }
    
    //    
    class MyRichInt(val self: Int /*     Int*/) {
      def myMax(i: Int): Int = {
        if (self < i) i else self
      }
    
      def myMin(i: Int): Int = {
        if (self < i) self else i
      }
    }
    
    

    暗黙クラス
    Scala 2.10(現2.13)の後に暗黙クラスが提供され、暗黙関数と同様にimplicitキーワードで修飾されるが、暗黙クラスは暗黙関数に対する超拡張である
      :
    (1)               
    (2)         “ ” “    ” “   ” ,          
      1:   (           )
    
    object Scala04_TestImplicit {
      def main(args: Array[String]): Unit = {
        println(2.myMax(6))
      }
        
      //implicit def convert(){}     
    
      /**
       *      
       * @param self
       */
      implicit class MyRichInt(val self: Int) {
        def myMax(i: Int): Int = {
          if (self < i) i else self
        }
    
        def myMin(i: Int): Int = {
          if (self < i) self else i
        }
      }
    }
    
      2:   (  ,        )
    
    //(2)               ,                  。                      ,
    object TestTransform extends PersonTrait {
      def main(args: Array[String]): Unit = {
        //(1)                  
        val teacher = new Teacher()
        teacher.eat()
        teacher.say()
      }
    
      class Teacher {
        def eat(): Unit = {
          println("eat...")
        }
      }
    }
    
    trait PersonTrait { /*       ,      ,      */ }
    object PersonTrait {
      //     :   Teacher =>   Person
      implicit class Person(user:Teacher) {
        def say(): Unit = {
          println("say...")
        }
      }
    }
    

    暗黙パラメータ
    一般的なメソッドまたは関数のパラメータはimplicitキーワードで暗黙的なパラメータとして宣言できます.
      :
    1.       ,             
    2.                       ,         。
    3.           ,          
    4.                      ()
      :
    
    object Scala03_TestImplicit {
      def main(args: Array[String]): Unit = {
        //      
        //  :         ,   implicit      
        //   :                 
        implicit var name = "banhua"
        sayHi
        //   sayHH()
      }
      def sayHi(implicit name:String="zhangshan")={
        println("hello:"+name)
      }
      def sayHH(na:String = "banhua") = {
          sayHi(na)
      }
    }
    

    暗黙解析メカニズム
    1.                  (    、   、    ),       
    
    2.               ,                  
          :                           
    

    異常
    import java.io.FileNotFoundException
    
    object Scala01_TestException {
      def main(args: Array[String]): Unit = {
        //1. Scala ,     (     )      (     )
        //throw FileNotFoundException
        try{
          var a:Int = 10 / 0
        }catch{
          //2.Scala        case e:    Exception,      
          case e:ArithmeticException=>println("       ")
          case e:Exception =>println("     ")
        }finally {
          println("finally   ")
        }
        //f11()
      }
    
      //3.         ,   @throws(classOf[    Exception]),         
      @throws(classOf[NumberFormatException])
      def f11()={
        "abc".toInt
      }
    }
    

    汎用型
    基本定義構文/汎用テンプレート:class ClassName[T]{}
    コヒーレントインバータ
    コヒーレント定義:class ClassName[+T](){}
    インバータ定義:class ClassName[-T](){}
    可変定義:class ClassName[T](){}
    //    :T,+T,-T
    class Student[-T] {}
    class Parent {}
    class Child extends Parent {}
    class SubChild extends Child {}
    
    object Test {
      def main(args: Array[String]): Unit = {
        //1.[T]   :      =       
        val stu11:Student[Child] = new Student[Child]
        // Error: Require Child,but now is Parent / SubChild
        //val stu12:Student[Child] = new Student[Parent]
        //val stu13:Student[Child] = new Student[SubChild]
    
        //2.[+T]  :   ,        +++
        val stu21: Student[Child] = new Student[Child]
        // Error: Require Child,but now is Parent
        //val stu22: Student[Child] = new Student[Parent]
        val stu23: Student[Child] = new Student[SubChild]
    
        //3.[-T]  :   ,        ---
        val stu31: Student[Child] = new Student[Child]
        val stu32: Student[Child] = new Student[Parent]
        // Error: Require Child,but now is SubChild
        //val stu33: Student[Child] = new Student[SubChild]
      }
    }
    

    上下限
    //1.Java    
    class Student {}
    class Parent {}
    class Child extends Parent {}
    class SubChild extends Child {}
    
    public class Test {
        public static void main(String[] args) {
            System.out.println("---      extends -> c  ---");
            testS(Child.class);
            testS(SubChild.class);
            //Error:Cannot be applied
            //testS(Parent.class);
            System.out.println("---      super  c ,  
        public static void testS(Class extends Child> c){
            System.out.println(c.getName());
        }
        //     super  c){
            System.out.println(c.getName());
        }
    }
    
    //2.Scala    
             :   <: class="" plist="" person="" student="" parent="" child="" extends="" subchild="" object="" scala05_testgeneric="" def="" main="" array="" unit="{" val="" println="" tests="" type="" parameter="" bounds="" childs="" now="" is="">: Child]      ->   /     ---")
        testX(child)
        testX(parent)
        //!!!      
        testX(subChild)
    
        println("--- [A]     ---")
        test0(child)
        test0(parent)
        test1(subChild)
        println("--- test0 == test1     ,           ---")
      }
    
      //  :       
      def testS[A <: child="" unit="{" println="" def="" testx="">: Child](a:A): Unit ={
        println(a)
      }
    
      //   
      def test0[A](a:A): Unit ={
        println(a)
      }
      def test1[Child](a:Child): Unit ={
        println(a)
      }
    }
    

    補足:Java Classオブジェクトの取得
    public class Test {
        public static void main(String[] args) throws ClassNotFoundException {
            System.out.println("--- Test.class ---");
            System.out.println(TestClass.class);
    
            System.out.println("--- Class.forName ---");
            System.out.println(Class.forName("TestClass"));
    
            System.out.println("--- t.getClass ---");
            TestClass t = new TestClass();
            System.out.println(t.getClass());
    
            /*Result:
            --- Test.class ---
            class TestClass
            --- Class.forName ---
                 
            class TestClass
            --- t.getClass ---
                  
                   
            class TestClass
            */
        }
    }
    
    public class TestClass {
        public TestClass() {
            System.out.println("       ");
        }
        static{
            System.out.println("     ");
        }
        {
            System.out.println("      ");
        }
    }
    

    汎用マウント
    //1.Java       
    //    ,              ,        
    class Parent{}
    class Child extends Parent{}
    class SubChild extends Child{}
    
    public class Test {
        public static void main(String[] args) {
            ArrayList std = new ArrayList();
            // new SubChild ; OK
            std.add(new Parent());
            ArrayList childs = new ArrayList<>();
            childs = std;
            //Java      Scala   ,       ,              
            //                ,              
            for (Child child : childs) {
                //ClassCastException: Parent cannot be cast to Child
                System.out.println(child);
            }
        }
    }
    
    //2.Scala     
    import scala.collection.mutable.ListBuffer
    
    //         :    ,      
    class Student[T] {
      var aaa:T = _
      def test(ttt : T): Unit ={
      }
    }
    class Parent {}
    class Child extends Parent { var a = 10}
    class SubChild extends Child {}
    
    object Scala05_TestGeneric {
      def main(args: Array[String]): Unit = {
    
        //1.       ,     Nothing,        
        var studs= ListBuffer[Parent]()
        studs.append(new Parent)
    
        //2.Scala               ,     
        var childs: ListBuffer[Child] = ListBuffer[Child]()
        //3.  List      ,          
        //childs = studs
      }
    }
    

    暗黙パラメータ[汎用]定義
    コンテキスト限定は、汎用および暗黙的な変換を組み合わせた生成物である.
    //    :
    def f[A : B](a: A) = println(a)               //  
    def f[A](a:A)(implicit arg:B[A]) = println(a) //  
       =>         ,                   ,        ?
    
    //    
    object Scala06_TestGeneric {
      def main(args: Array[String]): Unit = {
        println(f2(1, 2))
      }
      //def    [     :       ](    a,    b) =         .  (a,b)
      // :  [A:Ordering],                  ,    implicitly[Ordering[A]]       
      def f1[A:Ordering](a:A,b:A) =implicitly[Ordering[A]].compare(a,b)
    
      /*def    [    ]
        (    1 :    a,    b)
        (    2 : implicit     :      [    ]) =     .  (a,b)*/
      def f2[A](a: A, b: A)(implicit ord: Ordering[A]) = ord.compare(a, b)
    }