簡體   English   中英

了解Scala中的Case類和Traits

[英]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參數。

案例課有什么神奇之處 ?!

  • 默認字段將所有構造函數參數轉換為public readonly( 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方法,但是將valvar添加到類構造函數參數將解決問題。

案例類是不同的 - 為它們生成了一些默認方法。 這包括參數的val getters。 將案例類視為POJO - 這是一個有用的語法糖,因為它們不需要私有成員。

unapply生成一些其他有用的方法,例如copytoStringapplyunapply

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM