พารามิเตอร์ตัวสร้างสกาล่าเริ่มต้นที่ val ส่วนตัวหรือไม่


128

ฉันได้ลองแล้ว:

class Foo(bar: Int)

VS:

class Foo(private val bar: Int)

และพวกเขาดูเหมือนจะทำงานเหมือนกันแม้ว่าฉันจะไม่พบที่ใดก็ได้ที่บอกว่า(bar: Int)ขยายออกไป(private val bar: Int)ดังนั้นคำถามของฉันคือสิ่งเหล่านี้เหมือนกันหรือคล้ายกัน?

ในหมายเหตุด้านฉันพยายามใช้-Xprint:typerกับโค้ดเหล่านี้และพวกมันสร้างโค้ดเดียวกันยกเว้นบรรทัดเพิ่มเติมในอันที่สอง ฉันจะอ่านบรรทัดพิเศษนั้นได้อย่างไร

..
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>();
    ()
  }
}
..

คำตอบ:


177

bar: Int

นี่เป็นพารามิเตอร์ตัวสร้างแทบจะไม่ หากตัวแปรนี้ไม่ได้ใช้ที่ใดก็ได้ยกเว้นตัวสร้างมันจะยังคงอยู่ ไม่มีการสร้างฟิลด์ มิฉะนั้นprivate val barจะสร้างฟิลด์และกำหนดค่าของbarพารามิเตอร์ไว้ ไม่มีการทะเยอทะยานถูกสร้างขึ้น

private val bar: Int

การประกาศพารามิเตอร์ดังกล่าวจะสร้างprivate val barฟิลด์ที่มีทะเยอทะยานส่วนตัว พฤติกรรมนี้เหมือนกับข้างบนไม่ว่าพารามิเตอร์จะถูกใช้ข้างตัวสร้าง (เช่นในtoString()หรือไม่)

val bar: Int

เหมือนข้างต้น แต่ผู้ทะเยอทะยานที่เหมือนสกาล่าเป็นแบบสาธารณะ

bar: Int ในกรณีเรียน

เมื่อคลาสเคสเกี่ยวข้องโดยดีฟอลต์พารามิเตอร์แต่ละvalตัวจะมีตัวแก้ไข


15
ในชั้นเรียนกรณีพารามิเตอร์ทั้งหมดจะกลายเป็น val"สาธารณะ"
drexin

6
เอ้ยฉันใส่แว่นตาเป็นครั้งคราว แต่นี่มันมากเกินไป
om-nom-nom

1
@ om-nom-nom: ขอโทษฉันไม่เข้าใจ ฉันควรปรับปรุงการจัดรูปแบบ / โครงสร้างเพื่อให้อ่านง่ายขึ้นหรือไม่
Tomasz Nurkiewicz

1
@TomaszNurkiewicz: varพร้อมใช้งานและมีความหมายในการสร้างพารามิเตอร์คอนสตรัคเตอร์ในคุณสมบัติคลาส (ไม่แน่นอน) ทั้งในที่ไม่ใช่caseและcaseคลาส
Randall Schulz

8
ในหนังสือ 'Scala for the Impatient' ที่bar: Intรวบรวมไว้เพื่อprivate[this] val bar: Int
MyTitle

98

ในกรณีแรกbarเป็นเพียงพารามิเตอร์คอนสตรัค เนื่องจากตัวสร้างหลักคือเนื้อหาของคลาสเองจึงสามารถเข้าถึงได้ในคลาส แต่จากอินสแตนซ์นี้เท่านั้น ดังนั้นจึงเกือบเทียบเท่ากับ:

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

ในทางกลับกันในกรณีที่สองbarเป็นปกติข้อมูลส่วนตัวดังนั้นจึงสามารถเข้าถึงกรณีนี้และกรณีอื่น ๆ Fooของ ตัวอย่างเช่นคอมไพล์นี้ปรับ:

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

และวิ่ง:

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

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

แต่นี่ไม่ใช่:

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

9
นี่เป็นคำตอบที่ดีกว่าคำตอบที่ยอมรับได้ มันเน้นความแตกต่างระหว่างภาพเปลือยbar: Intและprivate val ...ภาพ
hraban
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.