[英]Understanding Case class and Traits in Scala
我有一個如下定義的簡單特征:
trait MyTrait {
def myStringVal: String
}
我的case類實現了這個特性如下:
case class MyCaseClass(myStringVal: String) extends MyTrait {
...
...
}
來自Java世界,我發現有點難以理解MyCaseClass實際上只是通過定義MyCaseClass的參數來實現它。 我知道你的字節代碼實際上會編寫getter和setter。 但如果沒有var或val,這怎么可能呢?
我的理解是,如果沒有var或val,則不會生成getter或setter方法。 在這種情況下,上面的案例類MyCaseClass如何實現myStringVal方法?
有時太多的Scala魔法難以理解,特別是遺留代碼。
您可能希望查看此博客文章,其中涵蓋了具體類型以及它們如此有用的原因。
在您的示例中,特性MyTrait
沒有用,除了能夠像java接口一樣運行。 請注意,scala中的默認可見性是公共的。 默認情況下,case類參數是不可變的,因此在您的示例中, val
會由編譯器自動推斷為myStringVal
參數。
案例課有什么神奇之處 ?!
val
) toString()
, equals()
和hashcode()
方法 apply()
和unapply()
方法,它們基本上只是一個方便構造函數,允許在不使用new
關鍵字的情況下實例化,並且默認情況下會生成一個包含選項包裝的case類的tuple
參數。 編輯:(案例)類的示例編譯器輸出(從scalatutorial.de復制)
一個簡單的scala類定義
class A1(v1: Int, v2: Double)
被編譯為java代碼
public class A1 extends java.lang.Object implements scala.ScalaObject {
public A1(int, double);
}
類似的案例類
case class A2(v1: Int, v2: Double)
被編譯為以下java類
public class A2 extends java.lang.Object implements
scala.ScalaObject,scala.Product,java.io.Serializable {
public static final scala.Function1 tupled();
public static final scala.Function1 curry();
public static final scala.Function1 curried();
public scala.collection.Iterator productIterator();
public scala.collection.Iterator productElements();
public double copy$default$2();
public int copy$default$1();
public int v1();
public double v2();
public A2 copy(int, double);
public int hashCode();
public java.lang.String toString();
public boolean equals(java.lang.Object);
public java.lang.String productPrefix();
public int productArity();
public java.lang.Object productElement(int);
public boolean canEqual(java.lang.Object);
public A2(int, double);
}
public final class A2$ extends scala.runtime.AbstractFunction2
implements scala.ScalaObject {
public static final A2$ MODULE$;
public static {};
public scala.Option unapply(A2);
public A2 apply(int, double);
public java.lang.Object apply(java.lang.Object, java.lang.Object);
}
Scala案例類為您實現了大量的樣板,並且將所有構造函數參數自動暴露為val
這是其中之一。
如果你試圖在常規類中避免使用val
,那樣:
trait MyTrait {
def myVal: String
}
class MyClass(myVal: String) extends MyTrait
編譯器將顯示錯誤消息,MyClass必須是抽象的,因為它不會覆蓋myVal
方法,但是將val
或var
添加到類構造函數參數將解決問題。
案例類是不同的 - 為它們生成了一些默認方法。 這包括參數的val getters。 將案例類視為POJO - 這是一個有用的語法糖,因為它們不需要私有成員。
unapply
生成一些其他有用的方法,例如copy
, toString
, apply
和unapply
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.