本頁說明 Contraband 型別系統如何在 Java 和 Scala 中編碼。
記錄類型會對應到 Java 或 Scala 類別,與 Scala 中的標準 case class 對應。
雖然標準 case class 在開始時很方便,但如果新增欄位,可能會破壞二進位制的相容性。Contraband 記錄(或偽 case class)允許您在不破壞二進位制相容性的情況下新增欄位,同時提供(幾乎)與普通 case class 相同的功能。
package com.example
@target(Scala)
type Person {
name: String!
age: Int
}
此結構描述會產生以下 Scala 類別
/**
* This code is generated using [[https://sbt.dev.org.tw/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package com.example
final class Person private (
val name: String,
val age: Option[Int]) extends Serializable {
override def equals(o: Any): Boolean = o match {
case x: Person => (this.name == x.name) && (this.age == x.age)
case _ => false
}
override def hashCode: Int = {
37 * (37 * (17 + name.##) + age.##)
}
override def toString: String = {
"Person(" + name + ", " + age + ")"
}
private[this] def copy(name: String = name, age: Option[Int] = age): Person = {
new Person(name, age)
}
def withName(name: String): Person = {
copy(name = name)
}
def withAge(age: Option[Int]): Person = {
copy(age = age)
}
def withAge(age: Int): Person = {
copy(age = Option(age))
}
}
object Person {
def apply(name: String, age: Option[Int]): Person = new Person(name, age)
def apply(name: String, age: Int): Person = new Person(name, Option(age))
}
與標準 case class 不同,Contraband 記錄不會實作 unapply
或公開的 copy
方法,這些方法無法以二進位制相容的方式演變。
它會針對每個欄位產生 withX(...)
方法,而不是 copy
。
> val x = Person("Alice", 20)
> x.withAge(21)
這是它產生的 Java 程式碼(在將目標註釋變更為 Java
之後)
/**
* This code is generated using [[https://sbt.dev.org.tw/contraband/ sbt-contraband]].
*/
// DO NOT EDIT MANUALLY
package com.example;
public final class Person implements java.io.Serializable {
public static Person create(String _name, java.util.Optional<Integer> _age) {
return new Person(_name, _age);
}
public static Person of(String _name, java.util.Optional<Integer> _age) {
return new Person(_name, _age);
}
public static Person create(String _name, int _age) {
return new Person(_name, _age);
}
public static Person of(String _name, int _age) {
return new Person(_name, _age);
}
private String name;
private java.util.Optional<Integer> age;
protected Person(String _name, java.util.Optional<Integer> _age) {
super();
name = _name;
age = _age;
}
protected Person(String _name, int _age) {
super();
name = _name;
age = java.util.Optional.<Integer>ofNullable(_age);
}
public String name() {
return this.name;
}
public java.util.Optional<Integer> age() {
return this.age;
}
public Person withName(String name) {
return new Person(name, age);
}
public Person withAge(java.util.Optional<Integer> age) {
return new Person(name, age);
}
public Person withAge(int age) {
return new Person(name, java.util.Optional.<Integer>ofNullable(age));
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
} else if (!(obj instanceof Person)) {
return false;
} else {
Person o = (Person)obj;
return name().equals(o.name()) && age().equals(o.age());
}
}
public int hashCode() {
return 37 * (37 * (37 * (17 + "com.example.Person".hashCode()) + name().hashCode()) + age().hashCode());
}
public String toString() {
return "Person(" + "name: " + name() + ", " + "age: " + age() + ")";
}
}