การทำความเข้าใจการแจงนับสกาลา


122

ฉันต้องบอกว่าฉันไม่เข้าใจชั้นเรียนการแจงนับของ Scala ฉันสามารถคัดลอกและวางตัวอย่างจากเอกสารประกอบได้ แต่ฉันไม่รู้ว่าเกิดอะไรขึ้น

object WeekDay extends Enumeration {
  type WeekDay = Value
  val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}
import WeekDay._
  • หมายถึงอะไรtype WeekDay = Valueและทำไมต้องเขียนแบบนั้น?
  • ทำไมval Mon = Value? นั่นหมายความว่าอย่างไร?
  • เหตุใดฉันจึงต้องนำเข้าWeekDay วัตถุ และ,
  • เมื่อผมเขียนval day = WeekDay.Monทำไมมันพิมพ์WeekDay.Valueไม่พิมพ์WeekDay?

2
ฉันได้เขียนภาพรวมเล็กน้อยเกี่ยวกับการแจงนับสกาลาและทางเลือกอื่น ๆ แล้วคุณอาจพบว่ามีประโยชน์: pedrorijo.com/blog/scala-enums/
pedrorijo91

ลักษณะที่ปิดผนึกเป็นทางเลือกที่ยอดเยี่ยม - stackoverflow.com/questions/11203268/what-is-a-sealed-trait
Joey Baruch

คำตอบ:


150

EnumerationลักษณะมีสมาชิกประเภทValueตัวแทนของแต่ละองค์ประกอบของการแจงนับ (ก็จริงระดับชั้น แต่ความแตกต่างไม่ได้เรื่องที่นี่)

จึงobject WeekDayสืบทอดสมาชิกประเภทนั้น บรรทัดtype WeekDay = Valueเป็นเพียงนามแฝงประเภท มันมีประโยชน์เพราะหลังจากที่คุณนำเข้าที่อื่นimport WeekDay._แล้วคุณสามารถใช้ประเภทนั้นได้เช่น:

def isWorkingDay(d: WeekDay) = ! (d == Sat || d == Sun)

แต่เวอร์ชันขั้นต่ำจะเป็น:

object WeekDay extends Enumeration {
  val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
}

และคุณไม่ต้องนำเข้าเนื้อหาของobject WeekDayแต่จากนั้นคุณจะต้องใช้ประเภทWeekDay.Valueและเพื่อตรวจสอบคุณสมบัติสมาชิกแต่ละคน ดังนั้นตัวอย่างจะกลายเป็น

def isWorkingDay(d: WeekDay.Value) = ! (d == WeekDay.Sat || d == WeekDay.Sun)

คำถามที่สองเกี่ยวกับความหมายของval Mon, ... = Value. Enumerationนี้แน่นอนมากทำให้เกิดความสับสนถ้าคุณไม่ได้มองเข้าไปในการดำเนินงานของ นี่ไม่ใช่การกำหนดประเภท! มันถูกเรียกแทนป้องกันวิธีการที่มีชื่อเดียวกัน , ซึ่งจะส่งกลับอินสแตนซ์ที่เป็นรูปธรรมของประเภทValueValue

มันจึงเกิดขึ้นที่คุณสามารถเขียนval a, b, c = fooใน Scala และสำหรับแต่ละค่าa, bและcวิธีการที่fooจะได้รับการเรียกอีกครั้งและอีกครั้ง Enumerationใช้เคล็ดลับนี้เพื่อเพิ่มตัวนับภายในเพื่อให้แต่ละค่าเป็นรายบุคคล

หากคุณเปิดเอกสาร Scala API Enumerationและคลิกที่Visibility: Allคุณจะเห็นวิธีการดังกล่าวปรากฏขึ้น


2
ขอบคุณสิ่งนี้สับสนมาก แต่ฉันคิดว่าถูกต้อง ฉันจะใช้คลาสเคสแบบปิดผนึกแทนดูเหมือนง่ายกว่า 100%
Karel Bílek

2
โดยส่วนตัวแล้วฉันชอบคลาสเคสแบบปิดผนึกด้วย ละเอียดกว่าเล็กน้อย แต่ hokus-pokus น้อยลงด้วยตัวนับภายในที่ไม่แน่นอนและอื่น ๆ ด้วย Scala 2.10 มีแนวคิดบางประการว่าการแจงนับ (ซึ่งแตกต่างจาก Java ไม่ใช่การสร้างภาษา แต่เป็นเพียงโซลูชันไลบรารี) สามารถเขียนได้ดีขึ้นโดยใช้มาโคร
0__

@ 0__ ขอถามว่าทำไมใช้คลาสปิดผนึกแทน enum ใน Scala ได้อย่างไร มีอะไรผิดปกติกับการแจงนับของ Scala หรือไม่?
x1a0

จะเกิดอะไรขึ้นถ้า Enum ให้ค่าตัวเองมีสมาชิก? ตัวอย่างเช่นคุณจะกำหนดเวลาเปิดทำการสำหรับแต่ละวันในสัปดาห์เช่นจันทร์ (8,20), ... , อา (0,0) ได้อย่างไร?
simou

1
@simou คุณควรใช้ลักษณะที่ปิดผนึกและคลาสย่อยจริง ฉันแทบจะไม่เรียกสถานการณ์นั้นว่า "การแจงนับ" คุณอาจเขียนได้ดีขึ้นOpen(Mon, 8, 20)และวันจะยังคงเป็นการแจกแจงแบบแบน
0__
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.