Các tham số xây dựng scala mặc định cho val riêng?


128

Tôi đã cố gắng:

class Foo(bar: Int)

vs

class Foo(private val bar: Int)

và họ dường như cư xử giống nhau mặc dù tôi không thể tìm thấy bất cứ nơi nào nói rằng (bar: Int)mở rộng để (private val bar: Int)câu hỏi của tôi là, những cái này giống hệt nhau?

Mặt khác, tôi đã cố gắng sử dụng -Xprint:typertrên các đoạn mã này và chúng tạo ra cùng một mã ngoại trừ một dòng bổ sung trong mã thứ hai. Làm thế nào để tôi đọc thêm dòng đó?

..
class Foo extends scala.AnyRef {
  <paramaccessor> private[this] val bar: Int = _;
  def <init>(bar: Int): this.Foo = {
    Foo.super.<init>();
    ()
  }
}
..


..
class Foo extends scala.AnyRef {
  <paramaccessor> private[this] val bar: Int = _;
  <stable> <accessor> <paramaccessor> private def bar: Int = Foo.this.bar;
  def <init>(bar: Int): this.Foo = {
    Foo.super.<init>();
    ()
  }
}
..

Câu trả lời:


177

bar: Int

Đây chỉ là một tham số xây dựng. Nếu biến này không được sử dụng ở bất cứ đâu ngoại trừ hàm tạo, nó vẫn ở đó. Không có trường được tạo ra. Mặt khác, private val bartrường được tạo và giá trị của bartham số được gán cho nó. Không có getter được tạo ra.

private val bar: Int

Khai báo tham số như vậy sẽ tạo ra private val bartrường với getter riêng. Hành vi này giống như trên, bất kể tham số được sử dụng bên cạnh hàm tạo (ví dụ: trong toString()hoặc không).

val bar: Int

Tương tự như trên nhưng getter giống Scala là công khai

bar: Int trong trường hợp lớp

Khi các lớp trường hợp có liên quan, theo mặc định, mỗi tham số có valsửa đổi.


15
Trong trường hợp các lớp, tất cả các tham số sẽ trở thành "công khai" val.
drexin

6
Trời ạ, thỉnh thoảng tôi vẫn đeo kính, nhưng điều này là quá nhiều.
om-nom-nom

1
@ om-nom-nom: xin lỗi, tôi không hiểu. Tôi có nên cải thiện định dạng / cấu trúc để làm cho nó dễ đọc hơn không?
Tomasz Nurkiewicz

1
@TomaszNurkiewicz: varcó sẵn và có ý nghĩa để hiển thị các tham số của hàm tạo thành các thuộc tính lớp (có thể thay đổi) cả trong các lớp không casecaselớp.
Randall Schulz

8
Trong cuốn sách 'Scala for the Impatient' được viết bar: Intthànhprivate[this] val bar: Int
MyTitle

98

Trong trường hợp đầu tiên, barchỉ là một tham số hàm tạo. Vì hàm tạo chính là nội dung của chính lớp, nên nó có thể truy cập được trong nó, nhưng chỉ từ chính trường hợp này. Vì vậy, nó gần như tương đương với:

class Foo(private[this] val bar:Int)

Mặt khác, trong trường hợp thứ hai barlà một trường riêng bình thường , do đó, trường hợp này có thể truy cập được các trường hợp khác Foo. Ví dụ, điều này biên dịch tốt:

class Foo(private val bar: Int) {
  def otherBar(f: Foo) {
    println(f.bar) // access bar of another foo
  }
}

Và chạy:

scala> val a = new Foo(1)
a: Foo = Foo@7a99d0af

scala> a.otherBar(new Foo(3))
3

Nhưng điều này không:

class Foo(bar: Int) {
  def otherBar(f: Foo) {
    println(f.bar) // error! cannot access bar of another foo
  }
}

9
đây là một câu trả lời tốt hơn câu trả lời được chấp nhận; nó làm nổi bật sự khác biệt giữa trần bar: Intprivate val ....
hraban
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.