zoukankan      html  css  js  c++  java
  • scala学习笔记:match与unapply()

    编写如下代码:

    object MatchTest {
        def foo(a : Any) : String =
            {
                a match {
                    case 1 => "int:1"
                    case x : Int if (x > 50) => "int(>50):" + x
                    case x : Int => "int:" + x
                    case (x, y) => "tuple:" + x + "," + y
                    case h :: t => "list:" + h + "," + t
                    case Array(90) => "array:90"
                    case Array(90, x) => "array:90," + x
                    case _ => ":("
                }
            }
    
        def main(args : Array[String]) {
            println(foo(1))
            println(foo(51))
            println(foo(49))
            println(foo((1, 2)))
            println(foo((1, 2, 3)))
            println(foo((3 -> 4)))
            println(foo(List(80, 81)))
            println(foo(Array(90, 91)))
        }
    }

    通过class代码反编译,看到java源代码如下:

      public String foo(Object a)
      {
        int i = 0; int j = 0;
    
        Object localObject1 = a;
        String str;
        if (BoxesRunTime.equals(BoxesRunTime.boxToInteger(1), localObject1)) { str = "int:1"; } else {
          if ((localObject1 instanceof Integer)) { i = 1; j = BoxesRunTime.unboxToInt(localObject1); if (j > 50) { str = new StringBuilder().append("int(>50):").append(BoxesRunTime.boxToInteger(j)).toString(); break label464;
            }
          }
          if (i != 0)
          {
            str = new StringBuilder().append("int:").append(BoxesRunTime.boxToInteger(j)).toString();
          } else if ((localObject1 instanceof Tuple2)) { Tuple2 localTuple2 = (Tuple2)localObject1; Object x = localTuple2._1(); Object y = localTuple2._2(); str = new StringBuilder().append("tuple:").append(x).append(",").append(y).toString();
          } else if ((localObject1 instanceof .colon.colon)) { .colon.colon localcolon = (.colon.colon)localObject1; Object h = localcolon.head(); List t = localcolon.tl$1(); str = new StringBuilder().append("list:").append(h).append(",").append(t).toString(); } else {
            if (ScalaRunTime..MODULE$.isArray(localObject1, 1)) { Object localObject2 = localObject1; Option localOption1 = Array..MODULE$.unapplySeq(localObject2); if ((!localOption1.isEmpty()) && (localOption1.get() != null) && (((SeqLike)localOption1.get()).lengthCompare(1) == 0)) { Object localObject3 = ((SeqLike)localOption1.get()).apply(0); if (BoxesRunTime.equals(BoxesRunTime.boxToInteger(90), localObject3)) { str = "array:90"; break label464; } } }
            if (ScalaRunTime..MODULE$.isArray(localObject1, 1)) { Object localObject4 = localObject1; Option localOption2 = Array..MODULE$.unapplySeq(localObject4); if ((!localOption2.isEmpty()) && (localOption2.get() != null) && (((SeqLike)localOption2.get()).lengthCompare(2) == 0)) { Object localObject5 = ((SeqLike)localOption2.get()).apply(0); Object x = ((SeqLike)localOption2.get()).apply(1); if (BoxesRunTime.equals(BoxesRunTime.boxToInteger(90), localObject5)) { str = new StringBuilder().append("array:90,").append(x).toString(); break label464; } } }
            str = ":(";
          }
        }
        label464: return str;
      }

    对于h::t的写法,其解释是:

    • 它其实是个中置表示法,等价于::(h,t)
    • ::是一个样例类!(java里该写的类名叫.colon.colon)

    再试一个简单的自定义object的例子:

    object Email {
        def unapply(str : String) : Option[(String, String)] = {
            val parts = str split "@"
            if (parts.length == 2) Some(parts(0), parts(1)) else None
        }
    
        def main(args : Array[String]) {
            val str = "bluejoe2008@gmail.com"
            str match {
                case Email(username, host) => println(s"username: $username  host: $host");
                case _ => println("this is not an email address ");
            }
        }
    }

    反编译代码:

      public void main(String[] args) {
        String str = "bluejoe2008@gmail.com";
        String str1 = str;
        Option localOption = unapply(str1);
        BoxedUnit localBoxedUnit;
        if (localOption.isEmpty()) {
          Predef..MODULE$.println("this is not an email address "); localBoxedUnit = BoxedUnit.UNIT;
        }
        else
        {
          String username = (String)((Tuple2)localOption
            .get())._1(); String host = (String)((Tuple2)localOption
            .get())._2(); Predef..MODULE$.println(new StringContext(Predef..MODULE$.wrapRefArray((Object[])new String[] { "username: ", "  host: ", "" })).s(Predef..MODULE$.genericWrapArray(new Object[] { username, host }))); localBoxedUnit = BoxedUnit.UNIT;
        }
      }
    

    如下内容摘录于http://cuipengfei.me/blog/2014/06/14/scala-unapply-method/

    unapplySeq和unapply的作用很是类似,例如这样:

    object Names {
      def unapplySeq(str: String): Option[Seq[String]] = {
        if (str.contains(",")) Some(str.split(","))
        else None
      }
    }

    这里定义了一个unapplySeq方法,用逗号作为分隔符来把字符串拆开。然后我们可以这样应用它:

    val namesString = "xiao ming,xiao hong,tom"
    namesString match {
      case Names(first, second, third) => {
        println("the string contains three people's names")
        println(s"$first $second $third")
      }
      case _ => println("nothing matched")
    }

    与上面的例子很是类似,不过编译器在这里替我们做的事情更多了:

    • 调用unapplySeq,传入namesString
    • 接收返回值并判断返回值是None,还是Some
    • 如果是Some,则将其解开
    • 判断解开之后得到的sequence中的元素的个数是否是三个
    • 如果是三个,则把三个元素分别取出,赋值给first,second和third
  • 相关阅读:
    不要忘了你曾经会写sql的
    一个定期压缩、删除过期数据的emp脚本
    xcode中如何安装多个版本的模拟器
    Xcode4.4中,代码无法高亮、无法自动补全
    xml有哪些解析技术?区别是什么?
    XML有哪些解析方式有何优缺点?xml有哪些解析技术?区别是什么?
    ASIHttpRequest网络请求第三方类库使用方法详解
    iPhone中如何判断当前相机是否可用
    NSArray 跟 NSMutableArray 使用 区别
    通常我们使用[NSDate date]方法得到的时间与当前时间不一致,如何解决?
  • 原文地址:https://www.cnblogs.com/bluejoe/p/5115867.html
Copyright © 2011-2022 走看看