• 样例类详解


    概述:

    case类在模式匹配和actor中经常使用到,当一个类被定义成为case类后,Scala会自动帮你创建一个伴生对象并帮你实现了一系列方法且带来了不少好处,如下:

    1.实现了apply方法,意味着你不需要使用new关键字就能创建该类对象
    1
    2
    3
    4
    5
    scala> case class People(name:String,age:Int)
    defined class People
      
    scala> val p = People("mobin",22) //省略了new关键字
    p: People = People(mobin,22)

      

    2.实现了unapply方法,可以通过模式匹配来获取类属性,是Scala中抽取器的实现和模式匹配的关键方法。
    1
    2
    scala> p match { case People(x,y) => println(x,y) }
    (mobin,22)

     

    3.实现了类构造参数的getter方法(构造参数默认被声明为val),但是当你构造参数是声明为var类型的,它将帮你实现setter和getter方法(不建议将构造参数声明为var)

     
    构造参数为val的情况(默认):
    1
    2
    3
    4
    5
    6
    scala> p.name
    res0: String = mobin
      
    scala> p.name = "mobin1" //报错,因为构造参数被声明为val所以并没有帮你实现setter方法
    <console>:10: error: reassignment to val
    p.name = "mobin1"
     
    构造参数为var的情况:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    scala> case class People(var name:String) //参数被声明为var
    defined class People
      
    scala> val p = People("mobin")
    p: People = People(mobin)
      
    scala> p.name = "mobin2"
    p.name: String = mobin2
      
    scala> p.name
    res1: String = mobin2 //修改成功,并没有报错

      

    4.还默认帮你实现了toString,equals,copy和hashCode等方法
     
    详述:
    我们再通过反编译来看看当你定义一个case类时编译器是怎么做的:
    同样定义一个简单的case类:
    Person.scala
    1
    case class Person(name: String,age : Int)

      

    通过终端中编译该文件(scalac Person.scala)后生成两个class文件,Person.class和Person$.class
     
    接下来再通过javap Person命令反编译Person.class,结果结果如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    Compiled from "Person.scala"
    public class com.mobin.scala.Person implements scala.Product,scala.Serializable {
    public static scala.Function1<scala.Tuple2<java.lang.String, java.lang.Object>, com.mobin.scala.Person> tupled();
    public static scala.Function1<java.lang.String, scala.Function1<java.lang.Object, com.mobin.scala.Person>> curried();
    public java.lang.String name();
    public int age();
    public com.mobin.scala.Person copy(java.lang.String, int);
    public java.lang.String copy$default$1();
    public int copy$default$2();
    public java.lang.String productPrefix();
    public int productArity();
    public java.lang.Object productElement(int);
    public scala.collection.Iterator<java.lang.Object> productIterator();
    public boolean canEqual(java.lang.Object);
    public int hashCode();
    public java.lang.String toString();
    public boolean equals(java.lang.Object);
    public com.mobin.scala.Person(java.lang.String, int);
    }
     
    再反编译Person$.class
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Compiled from "Person.scala"
    public final class com.mobin.scala.Person$ extends scala.runtime.AbstractFunction2<java.lang.String, java.lang.Object, com.mobin.scala.Person> implements scala.Serializable {
    public static final com.mobin.scala.Person$ MODULE$;
    public static {};
    public final java.lang.String toString();
    public com.mobin.scala.Person apply(java.lang.String, int);
    public scala.Option<scala.Tuple2<java.lang.String, java.lang.Object>> unapply(com.mobin.scala.Person);
    public java.lang.Object apply(java.lang.Object, java.lang.Object);
    }
     
    通过反编译以上两个class文件可以知道,当你将一个类定义为case类后,编译器就自动帮你实现了一系列方法。
     
    我们再来对比下去掉case关键字将类定义为普通类后反编译的结果
    1
    class Person(var name : String,var age : Int) //将参数声明为var

      

    反编译的结果如下:
    1
    2
    3
    4
    5
    6
    7
    8
    Compiled from "Person.scala"
    public class com.mobin.scala.Person {
    public java.lang.String name();
    public void name_$eq(java.lang.String);
    public int age();
    public void age_$eq(int);
    public com.mobin.scala.Person(java.lang.String, int);
    }

      

    比较之下case类比普通的类多了不少的方法,所以当你不需要这些额外的方法时你就可以将类定义为普通的类,但是你又不想通过new关键字来创建实例,你可以在普通类中实现apply方法达到此目的。
     
    因为case本就旨在创建的是不可变数据,所以在使用模式匹配时显得极为容易
  • 相关阅读:
    mybatis由浅入深day01_6SqlMapConfig.xml(6.2settings全局参数配置_6.3typeAliases(类型别名)_6.4typeHandlers(类型处理器)_6.5mappers(映射配置))
    mybatis由浅入深day01_5.3 Mapper动态代理方法
    mybatis由浅入深day01_5mybatis开发dao的方法(5.1SqlSession使用范围_5.2原始dao开发方法)
    mybatis由浅入深day01_ 4.11总结(parameterType_resultType_#{}和${}_selectOne和selectList_mybatis和hibernate本质区别和应用场景)
    mybatis由浅入深day01_4.9删除用户_4.10更新用户
    mybatis由浅入深day01_4.7根据用户名称模糊查询用户信息_4.8添加用户((非)自增主键返回)
    mybatis由浅入深day01_4入门程序_4.6根据用户id(主键)查询用户信息
    mybatis由浅入深day01_3mybatis框架介绍
    mybatis由浅入深day01_1课程安排_2对原生态jdbc程序中问题总结
    工作流JBPM_day02:3-预定义的活动1_4-预定义的活动2+在图片上高亮显示正在执行的上活动
  • 原文地址:https://www.cnblogs.com/yejibigdata/p/6481832.html
Copyright © 2020-2023  润新知