当前位置: 首页 > 工具软件 > Classp > 使用案例 >

Scala之case class

穆承运
2023-12-01

我们在模式匹配中可以见到case

a match {
    case b => ...
    case _ => ...
}

我们在类定义时,有时也会见到case关键字

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

那么,在类上加上case关键字意味着什么呢?

伴生对象

编译Person.scala会产生两个class, Person.class和Person$class. 编译器给scala自动添加了一个伴生对象object Person

apply()方法和unapply()方法

伴生对象Person里面实现了apply()方法如下,

public Person apply(int age, String name){
    return new Person(age, name);
}

所以我们创建一个实例的时候不需要使用关键字new,可以直接通过Person(age,name)来得到一个实例对象

伴生对象Person里面还实现了unapply()方法,将对象转为可选元组集合Option[Tuple]

    public scala.Option<scala.Tuple2<Object, Object>> unapply(Person person) {
        if (person == null) {
            return scala.None$.MODULE$;
        }
        return new scala.Some(new scala.Tuple2$mcll$sp(person.age, person.name))

我们来看看代码

object CaseClassDriver {
  def main(args: Array[String]): Unit = {
    val p = Person(13,"李程")
    println(p.toString)

    val p$ = Person.unapply(p)
    println(p$.toString)
  }
}

/**
  * case class 编译后会生成两个class文件Person.class和Person$.class
  * Person$.class是伴生对象,实现了apply方法和unapply方法
  * apply方法返回一个实例对象
  * unapply方法将对象转为元组
  */
case class Person(age: Int, name: String)

Case Class默认是Immutable

case类的字段会被编译器默认加上val关键字。
所以Person.class中的age和name都被定义成了final, 且伴生对象Person$.class的定义也是

public final class Person$ {
    ...
}

toString()、hashCode()和equals()方法

Scala编译器负责(根据字段)给Case类重写toString()、hashCode()和equals()方法。

copy()方法,快速复制自己,并可以做少量变化

package base.day05.caseobject

/**
  * @description CaseObjDriver
  * @author ZerlindaLi create at 2019/4/29 20:32
  * @version 1.0.0
  */
object CaseClassDriver {
  def main(args: Array[String]): Unit = {
    val p = Person(13,"李程")
    val p2 = p.copy()
    val p22 = Person(13,"李程")
    val p3 = p.copy(age=14)
    println(p.toString + p2.toString + p3.toString)
    println(p.hashCode)
    println("p.equals(p):"+p.equals(p))
    println("p.equals(p22):"+p.equals(p22))
    println("p.equals(p2):"+p.equals(p2))
    println("p2.equals(p3):"+p2.equals(p3))
    val p$ = Person.unapply(p)
    println(p$.toString)
  }
}

/**
  * case class 编译后会生成两个class文件Person.class和Person$.class 默认为Immutable
  * Person$.class是伴生对象,实现了apply方法和unapply方法
  * apply方法返回一个实例对象
  * unapply方法将对象转为元组
  * 重写了toString,equals,hashCode方法
  */
case class Person(age: Int, name: String)

运行结果为

Person(13,李程)Person(13,李程)Person(14,李程)
-89502882
p.equals(p):true
p.equals(p22):true
p.equals(p2):true
p2.equals(p3):false
Some((13,李程))

实现Product和Serializable接口

Case类还实现了scala.Product和scala.Serializable接口(Product和Serializable实际上都是Traits)。

    // Product
    // def productArity: Int
    // def productElement(n: Int): Any
    // def productIterator: Iterator[Any]
    // def productPrefix = ""
    
    public int productArity() {
        return 2;
    }
    public Object productElement(int n) {
        switch (n) {
            case 0: return age();
            case 1: return name();
            default: throw new IndexOutOfBoundsException();
        }
    }
    public scala.collection.Iterator productIterator() {
        return scala.runtime.ScalaRunTime$.MODULE$.typedProductIterator(this);
    }
    public String productPrefix() {
        return "Person";
    }
 类似资料: