scala3-case-class-basic

case class 概念

样例类,scala针对这种特殊类提供很多默认的方便的功能,更重要的是,和模式匹配完美配合

case class create

case class Fruit(name:String,weight:Double):
end Fruit

case class instance create

val fruit = Fruit("苹果",23.5)

case class背后的工作

scala会针对case class创建对应的伴生对象,并且自动重写了部分方法

  • toString
  • hashCode
  • ==
  • copy
  • tupeld
val fruit = Fruit("苹果",23.5)
println(fruit)

结果

Fruit(苹果,23.5)

val fruit = Fruit("苹果",23.5)
val fruit2 = Fruit("苹果",23.5)
println(fruit == fruit2)

true

如果是一个普通的class

class Fruit2(name:String,weight:Double):
end Fruit2
val fruit = Fruit2("苹果",23.5)
val fruit2 = Fruit2("苹果",23.5)
println(fruit == fruit2)

结果

false

copy的便利性

val fruit = Fruit("苹果",23.5)
val fruit2 = fruit.copy(name = "橘子")
println(fruit2)

替换名称,其他数据不变,可以利用已有对象轻松创建新对象

tupled

利用元组转变为对应的case class

val tuple = ("苹果",23.5)
val fruit = (Fruit.apply _).tupled(tuple)
println(fruit)

关于tupled

Creates a tupled version of this function: instead of 2 arguments, it accepts a single Tuple2 argument.
Returns:
a function f such that f((x1, x2)) == f(Tuple2(x1, x2)) == apply(x1, x2)

hashcode

这个我们要看下生成的Java代码

public int hashCode() {
   int var1 = -889275714;
   var1 = Statics.mix(var1, this.productPrefix().hashCode());
   var1 = Statics.mix(var1, Statics.anyHash(this.name()));
   var1 = Statics.mix(var1, Statics.doubleHash(this.weight()));
   return Statics.finalizeHash(var1, 2);
}

可以看出开头结尾有两次计算,中间经过和对应数据项的计算,也就是说有多少个字段,中间就有多少次哈希

这个Statics就是scala.Runtime下面的。

mix的实现

public static int mix(int hash, int data) {
  int h = mixLast(hash, data);
  h = Integer.rotateLeft(h, 13);
  return h * 5 + 0xe6546b64;
}

有兴趣的话,可以逐一读一下源码

模式匹配的功能,这里暂时不展开。

编译观察

scalac Fruit.scala

编译结果

使用javap查看

javap Fruit.class

结果

public class Fruit implements scala.Product,java.io.Serializable {
  public static Fruit apply(java.lang.String, double);
  public static Fruit fromProduct(scala.Product);
  public static Fruit unapply(Fruit);
  public Fruit(java.lang.String, double);
  public scala.collection.Iterator productIterator();
  public scala.collection.Iterator productElementNames();
  public int hashCode();
  public boolean equals(java.lang.Object);
  public java.lang.String toString();
  public boolean canEqual(java.lang.Object);
  public int productArity();
  public java.lang.String productPrefix();
  public java.lang.Object productElement(int);
  public java.lang.String productElementName(int);
  public java.lang.String name();
  public double weight();
  public Fruit copy(java.lang.String, double);
  public java.lang.String copy$default$1();
  public double copy$default$2();
  public java.lang.String _1();
  public double _2();
}
javap Fruit$.class

结果

public final class Fruit$ implements scala.deriving.Mirror$Product,java.io.Serializable {
  public static final Fruit$ MODULE$;
  public static {};
  public Fruit apply(java.lang.String, double);
  public Fruit unapply(Fruit);
  public java.lang.String toString();
  public Fruit fromProduct(scala.Product);
  public java.lang.Object fromProduct(scala.Product);
}

这样我们就不难理解它里面为什么有_1, _2这种方法,并且他还有apply和unapply,一个方便创建对象,一个可以进行模式匹配。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

singkingcho

有帮助?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值