zoukankan      html  css  js  c++  java
  • scala之case class 和case object

    首先我们我们对case class 和case object类型对象进行反编译

    首先来编译 case class,有如下编译内容:

    case class Person(age:Int,name:String)

    它会产生两个文件如下:

    Person.class的编译内容如下:

    import scala.Function1;
    import scala.Option;
    import scala.Product;
    import scala.Product.class;
    import scala.Serializable;
    import scala.Tuple2;
    import scala.collection.Iterator;
    import scala.reflect.ScalaSignature;
    import scala.runtime.BoxesRunTime;
    import scala.runtime.ScalaRunTime.;
    import scala.runtime.Statics;
     
    @ScalaSignature(bytes="615-b1B1312217a1U3sg>t'"A2215q*W1429;z}
    11321725=1"a26143!Q17!C16g14fG.Y5323!17a!178z%2247CA41419	q1BA4Qe>$Wo25;17529118BA		5125VM]5bY&T24M257f17!252A!f1
    3!18aA1hKV	Q352-%17q332419:$2C
    15#51117B112	5<W
    	5	7117)26!C195!a.Y7f+5i2C116"29	9q$32!17511K]3eK26L!AI183
    M#(/278h21	13235&1	E	21!330321q23-\3!1721931"1)325a20N\5u}Q2517f1123175)2Q"12	11M1325A11	11m1325A15	15921717!C1_5!1m289z)
    I3'
    5'52
    1711221729YR6%AA2uAqa
    1182195A'1d_BLH5Z3gCVdG15J25223UR#!628,3]2"1O31143eR!AO30219Ut7
    [3dW22$'B131	3)	gN\8uCRLwN\53}e1817#308dQ22287.263WCJL23M\2f172915!%A52511abY8qs18"WMZ1vYR$#'F1CU	ib7C4E155I17I#227A20x14Z;diB19XMZ5y+515CA$M275A%BA%K317a23M\4113-11AA[1wC&17!5195292		17"121311(o283vGRf%/27;z172916!!A52E11a229:pIV28G/187f[22tG1562S+B17qaU53)"171!178z17291v*!AA2U	11311921729A6!!A5Be11q229:pIV28G/19;fe6$xN]1125B251L24*143qS!!245221
    |G14\3di&|g.32`9
    A17
    ^3sCR|'15C4b155I1712217
    fg.R9vC2$"a25417529!23BA3	52917un287fC:DqA2212237!11C4i155I17I5217!f715["pI22$18!65W2		17"17m3!!xn21;sS:<G#1$	15941717!C!_61Q-];bYN$"a259	15Yk2317!a1%309!OAA11832524A2)feN|g1452+i26917AAA1183)8c1;w31A)qO_1130S5	1P32z1759!/308uS6,23BA>y5E	%m29;sC14$h)308di&|gN
    56OQ$	! 112g"9114^A1
    11b7"CA1i65I17QA2321	715297z)21I19QAA4172125r1611221721Yr16113017%	Y1^A1
    311i!A4v]6415\=21	5=1714	6155E17QC543'A!AB(qi&|g14E33/)R$C2226!17a1V;qY22204"CA15319		1711*3
    AH5
    5
    3C!2417!C53G	1B]3bIJ+7o287wKR1717Q5	41562918bAA2117
    1qJ256fGR4")
    public class Person
      implements Product, Serializable
    {
      private final int age;
      private final String name;
     
      public static Option<Tuple2<Object, String>> unapply(Person paramPerson)
      {
        return Person..MODULE$.unapply(paramPerson);
      }
     
      public static Person apply(int paramInt, String paramString)
      {
        return Person..MODULE$.apply(paramInt, paramString);
      }
     
      public static Function1<Tuple2<Object, String>, Person> tupled()
      {
        return Person..MODULE$.tupled();
      }
     
      public static Function1<Object, Function1<String, Person>> curried()
      {
        return Person..MODULE$.curried();
      }
     
      public int age(){return this.age; } 
      public String name() { return this.name; } 
      public Person copy(int age, String name) { return new Person(age, name); } 
      public int copy$default$1() { return age(); } 
      public String copy$default$2() { return name(); } 
      public String productPrefix() { return "Person"; } 
      public int productArity() { return 2; } 
      public Object productElement(int x$1) { int i = x$1; switch (i) { default:
          throw new IndexOutOfBoundsException(BoxesRunTime.boxToInteger(x$1).toString());
        case 1:
        case 0: } return BoxesRunTime.boxToInteger(age()); } 
      public Iterator<Object> productIterator() { return ScalaRunTime..MODULE$.typedProductIterator(this); } 
      public boolean canEqual(Object x$1) { return x$1 instanceof Person; } 
      public int hashCode() { int i = -889275714; i = Statics.mix(i, age()); i = Statics.mix(i, Statics.anyHash(name())); return Statics.finalizeHash(i, 2); } 
      public String toString() { return ScalaRunTime..MODULE$._toString(this); } 
      public boolean equals(Object x$1) { int i;
        if (this == x$1) break label92; Object localObject = x$1; if (localObject instanceof Person) i = 1; else i = 0; if (i == 0) break label96; Person localPerson = (Person)x$1; if (age() != localPerson.age()) break label88; str = localPerson.name();
        String tmp54_44 = name(); if (tmp54_44 != null) break label67; tmp54_44; if (str == null) break label75; label67: label75: label88: label92: label96: break label88: } 
      public Person(int age, String name) { Product.class.$init$(this);
      }
    }

    Person$.class的编译内容如下:

    import scala.Option;
    import scala.Serializable;
    import scala.Some;
    import scala.Tuple2;
    import scala.runtime.AbstractFunction2;
    import scala.runtime.BoxesRunTime;
     
    public final class  extends AbstractFunction2<Object, String, Person>
      implements Serializable
    {
      public static final  MODULE$;
     
      static
      {
        new ();
      }
     
      public final String toString()
      {
        return "Person"; } 
      public Person apply(, String name) { return new Person(age, name); } 
      public Option<Tuple2<Object, String>> unapply() { return new Some(new Tuple2(BoxesRunTime.boxToInteger(x$0.age()), x$0.name())); } 
      private Object readResolve() { return MODULE$; } 
      private () { MODULE$ = this;
      }
    }

    分析:
    1、case 类在编译的时候会自动增加一个 单列对象(single object)。

    2、产生了一个apply的方法,那么我们可以直接把对象当作方法来用,比如 Person(12,Tom),就代表已经创建一个Person的对象,同时调用了這个对象的apply方法

    3、产生了一个upapply的方法,也就是说在模式匹配的时候可以用case class Person来作为 age和name的提取器

    4、继承了Product和Serializable(implements Product, Serializable),也就是说已经序列化和可以应用Product的方法

    5、age和name字段都是由final 修饰,也就是说是不可改变的,那么用scala的语言来阐述,那么就是 case class 的参数默认是  immutable类型的。

    6、也包含了toString,hashCode,copy,equals方法。

    我们再对case object person进行编译

    case object Person

    结果如下:

     Person.class的编译内容

    import scala.Product;
    import scala.Product.class;
    import scala.Serializable;
    import scala.collection.Iterator;
    import scala.runtime.BoxesRunTime;
    import scala.runtime.ScalaRunTime.;
     
    public final class 
      implements Product, Serializable
    {
      public static final  MODULE$;
     
      static
      {
        new ();
      }
     
      public String productPrefix()
      {
        return "Person"; } 
      public int productArity() { return 0; } 
      public Object productElement() { int i = x$1; throw new IndexOutOfBoundsException(BoxesRunTime.boxToInteger(x$1).toString()); } 
      public Iterator<Object> productIterator() { return ScalaRunTime..MODULE$.typedProductIterator(this); } 
      public boolean canEqual() { return x$1 instanceof ; } 
      public int hashCode() { return -1907849355; } 
      public String toString() { return "Person"; } 
      private Object readResolve() { return MODULE$; } 
      private () { MODULE$ = this; Product.class.$init$(this);
      }
    }

    Person$.class的编译内容

    import scala.Product;
    import scala.Product.class;
    import scala.Serializable;
    import scala.collection.Iterator;
    import scala.runtime.BoxesRunTime;
    import scala.runtime.ScalaRunTime.;
     
    public final class 
      implements Product, Serializable
    {
      public static final  MODULE$;
     
      static
      {
        new ();
      }
     
      public String productPrefix()
      {
        return "Person"; } 
      public int productArity() { return 0; } 
      public Object productElement() { int i = x$1; throw new IndexOutOfBoundsException(BoxesRunTime.boxToInteger(x$1).toString()); } 
      public Iterator<Object> productIterator() { return ScalaRunTime..MODULE$.typedProductIterator(this); } 
      public boolean canEqual() { return x$1 instanceof ; } 
      public int hashCode() { return -1907849355; } 
      public String toString() { return "Person"; } 
      private Object readResolve() { return MODULE$; } 
      private () { MODULE$ = this; Product.class.$init$(this);
      }
    }

    分析
    1、case object Person相比于case class Person(age:Int,name:String)缺少了apply、unapply方法,因为case object

    是没有参数输入的,所以对于apply 和unapply的方法也自然失去。

    2、因为class 和 object 在编译的时候,object是只有一个编译文件,而当两者加上case之后发现两者都是有2个编译文件,也就是说case object 不在像object那样仅仅是一个单列对象,而是有像类(class)一样的特性。

    3、都有toString,hashCode,copy,equals方法和继承了Product和Serializable(implements Product, Serializable)

    因为前面是case class Person(age:Int,name:String)和case object Person,因为class和object特征导致前者有参数,而后者无参数。而导致一些本质上的区别,下面再来编译一下 case class Person,此刻是不带参数的。发现和

    case object Person 编译的结果一模一样。那么此刻是否认为case object 這个修饰這个是多余的。

    从功能上来说是yes,

    我们可以看看Mark Lewis,对此的阐述[2]

    Functionally, the difference is the same as between a class and an object. The former creates a blueprint for making objects and the latter defines a singleton object in the scope in which it is declared. In both situations, adding the "case" keyword causes some syntactic sugar to be included. Less of that is needed for the objects than the classes.
     
    Starting with Scala 2.10, you should always use case objects instead of case classes with no arguments. The primary use case here is that you have values you want to pattern match on and some of those need arguments and others don't. The ones that don't take arguments should be declared as case objects while the ones that do should be case classes. This makes sense given that you really don't need multiple instances of an immutable type where the instances would all have identical values.

    可以這么总结一句话,当Person有参数的时候,用case class ,当Person没有参数的时候那么用case object。這一样意义在于区分 有参和无参

    总结

    1、case 关键词只用来修饰  class 和object,也就是说只有case class 和case object的存在 ,

    而没有case trait 或者class **这一说

    2、case object /class A 这个A 是经过序列化,而且继承了Product特性同时有toString,hashCode,copy,equals方法

    3、case class 经常可以用于解析和提取

    4、有参用case class ,无参用case object

  • 相关阅读:
    FreeSWITCH一些需求应对
    CentOS 7安装Mysql并设置开机自启动
    RTP学习笔记
    SDP学习笔记
    Quartz实用二三事
    Quartz:ERROR threw an unhandled Exception
    CentOS 7一些常用配置
    Java获取音频文件(MP3)的播放时长
    使用Callable和Future接口创建线程
    join() 方法详解及应用场景
  • 原文地址:https://www.cnblogs.com/itboys/p/12747218.html
Copyright © 2011-2022 走看看