簡體   English   中英

Scala特性繼承奇怪的行為

[英]Scala trait inheritance strange behavior

有人可以解釋為什么這個程序打印0而不是4?

trait Rectangular {
  def width: Int
  def height: Int
  val area = width * height
}
case class Square(val size: Int) extends Rectangular {
  val width = size
  val height = size
}

print(Square(2).area)

但是當我使vals懶惰時它會起作用

trait Rectangular {
  def width: Int
  def height: Int
  val area = width * height
}
case class Square(val size: Int) extends Rectangular {
  lazy val width = size
  lazy val height = size
}

print(Square(2).area)

這是Scala構造val成員的方式的一個不幸的問題。

trait Rectangular {
  def width: Int
  def height: Int
  val area = width * height
}
case class Square(val size: Int) extends Rectangular {
  val width = size
  val height = size
}

在內部,Scala使Square私有成員稱為widthheight 它將它們初始化為零。 然后,在Square構造函數中,它設置它們。 基本上,它做了一些接近這個Java代碼的東西。

public abstract class Rectangular {
    private int area;
    public Rectangular() {
        area = width() * height();
    }
    public abstract int width();
    public abstract int height();
    public int area() { return area; }
}
public class Square extends Rectangular {
    private int width, height;
    public Square(int size) {
        Rectangular();
        width = size;
        height = size;
    }
    public int width() { return width; }
    public int height() { return width; }
}

請注意,在Square構造函數之前調用Rectangular構造函數,因此area在設置之前會看到默認的零widthheight值。 正如您已經發現的那樣,使用lazy val解決問題。

trait Rectangular {
  def width: Int
  def height: Int
  val area = width * height
}
case class Square(val size: Int) extends Rectangular {
  lazy val width = size
  lazy val height = size
}

或者,您可以使用早期初始化程序語法強制以正確的順序寫入值。

trait Rectangular {
  def width: Int
  def height: Int
  val area = width * height
}
case class Square(val size: Int) extends {
  val width = size
  val height = size
} with Rectangular

lazy val解決方案通常是優選的,因為它可以減少道路上的意外。

有關更多信息,請參閱有關此特定主題的Scala常見問題解答

問題是你的特質中的val在你的類的val之前被初始化了。

因此,當您調用構造函數時,第一個area將被初始化。 它將其值設置為width * height widthheight都沒有初始化,因此它們的值為零。 這意味着area = 0 * 0 = 0

之后, widthheight設置為size的值,但此時對於區域來說太晚了。

它適用於lazy val因為lazy vals檢查它們是否在訪問時被初始化,如果沒有則初始化它們。 常規val沒有這樣的檢查。

暫無
暫無

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

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