ฟังก์ชั่น Swift กับคุณสมบัติที่คำนวณ


26

ว่าฉันมีชั้นเรียนEventดังนี้

class Event {
    private var attendees: [Person] = []

    // Case 1
    //*******
    // Should I use a func…
    func countOfAttendees() -> Int {
        return attendees.count
    }

    // …or a var
    var countOfAttendees: Int {
        return attendees.count
    }

    // Case 2
    //*******
    // Should I use a func…
    func countOfPaidAttendees() -> Int {
        return attendees.filter({$0.hasPaid}).count
    }

    // …or a var
    var countOfPaidAttendees: Int {
        return attendees.filter({$0.hasPaid}).count
    }
}

เป็นการดีที่สุดที่จะใช้ฟังก์ชั่นหรือคุณสมบัติที่คำนวณได้ใน 2 กรณีที่ระบุไว้ข้างต้น?


2
stackoverflow.com/questions/24035276/ ...... ในระยะสั้น: 'ให้ฟังก์ชั่นของคุณเป็นฟังก์ชั่นและคุณสมบัติของคุณเป็นคุณสมบัติ'
Robert Harvey

คำตอบ:


14

ปฏิบัติตามหลักการเข้าถึงแบบฟอร์มเดียวกัน

บริการทั้งหมดที่นำเสนอโดยโมดูลควรพร้อมใช้งานผ่านสัญกรณ์ที่เหมือนกันซึ่งไม่ได้ทรยศว่าพวกเขาจะดำเนินการผ่านการจัดเก็บหรือผ่านการคำนวณ

สำหรับฉันแล้วนี่หมายความว่าฉันจะไม่เขียน funcs ที่ไม่มีข้อโต้แย้งและคืนค่า ฉันมักจะใช้คุณสมบัติที่คำนวณได้ ด้วยวิธีนี้ถ้าฉันตัดสินใจที่จะเปลี่ยนคุณสมบัติที่คำนวณได้ในภายหลังเป็นคุณสมบัติที่เก็บไว้ฉันสามารถทำได้โดยไม่ต้องมีการลบ parens ทุกที่ในแอปของฉัน ซึ่งดูเหมือน IMHO สิ้นเปลือง

และถ้าฉันเปลี่ยนคุณสมบัติที่เก็บไว้เป็นสิ่งที่คำนวณได้ฉันไม่ต้องเพิ่ม parens ไปยังส่วนท้ายของมันและทุก ๆ ที่มันถูกใช้ในแอพ


ตอนแรกฉันไปกับคำตอบที่ซับซ้อนของ @ Anton แต่ในทางปฏิบัติฉันรู้ว่านี่เป็นวิธีที่ฉันทำ…คุณสมบัติเป็นค่าเริ่มต้น
Ashley Mills

17

ฉันจะบอกว่ามันขึ้นอยู่กับความซับซ้อนของการคำนวณเทียบกับความถี่ในการใช้งาน

  • ถ้าเป็นO(1)/ *ให้ใช้คุณสมบัติที่คำนวณได้
  • ถ้าเป็นO(N)+/ rare-useให้ใช้ฟังก์ชัน
  • หากเป็นO(N)+/ frequent-useให้คิดว่าในอนาคตคุณอาจตัดสินใจใช้แคชหรือเทคนิค "ชาญฉลาด" อื่น ๆ เพื่อชดเชยความซับซ้อนหาก "ใช่" ให้ใช้คุณสมบัติหาก "ไม่ - ไม่ - ไม่หนักเกินไป" จากนั้นใช้ฟังก์ชัน .

2
ตลกว่าฉันเริ่มทำมันโดยใช้เหตุผลเดียวกัน หากคุณ "สามารถ" ให้ความประทับใจในการเป็นคุณสมบัติแม้ว่าคุณจะต้องทำการประมวลผลที่มีน้ำหนักเบาตราบใดที่มันไม่เปลี่ยนวัตถุให้เป็นคุณสมบัติ
ฝ่ายขาย Dielson

9

ฉันเพิ่งเริ่มเรียนรู้ Kotlin และพวกเขามี heuristic ที่ดีเกี่ยวกับเมื่อใช้คุณสมบัติที่คำนวณได้:

ฟังก์ชั่นและคุณสมบัติ

ในบางกรณีฟังก์ชันที่ไม่มีอาร์กิวเมนต์อาจใช้แทนกันได้กับคุณสมบัติแบบอ่านอย่างเดียว แม้ว่าความหมายจะคล้ายกัน แต่ก็มีการประชุมโวหารบางอย่างเมื่อต้องการหนึ่งไปยังอีก

ชอบคุณสมบัติมากกว่าฟังก์ชั่นเมื่ออัลกอริทึมพื้นฐาน:

  • ไม่โยน
  • มีความซับซ้อน O (1)
  • มีราคาถูกในการคำนวณ (หรือcaсhedในการเรียกใช้ครั้งแรก)
  • ส่งคืนผลลัพธ์เดียวกันผ่านการเรียกใช้

- https://kotlinlang.org/docs/reference/coding-conventions.html


การ 'ไม่โยน' ก็มีความสำคัญสำหรับ Swift เนื่องจากคุณสมบัติไม่สามารถโยนได้ (ยัง?)
alejandromp

"มีความซับซ้อน O (1)" ถูกลบออกจากเอกสาร
Mahmoud Shahoud

7

ใน Swift ฟังก์ชันที่ไม่มีพารามิเตอร์และคุณสมบัติที่คำนวณได้มีความสามารถเกือบเหมือนกัน (อาจมีความแตกต่างที่ฟังก์ชั่นที่ไม่มีพารามิเตอร์ก็ปิดเช่นกันในขณะที่คุณสมบัติที่คำนวณไม่ได้)

ความแตกต่างคือความหมาย หากรหัสของคุณทำการกระทำและส่งคืนตัวอย่างคำอธิบายของผลลัพธ์ของการกระทำนั้นฉันจะใช้ฟังก์ชัน หากรหัสของคุณคำนวณคุณสมบัติ แต่จากมุมมองของผู้ใช้สิ่งนี้อาจเป็นคุณสมบัติที่เก็บไว้หรืออาจเป็นคุณสมบัติที่จัดเก็บที่ต้องอัปเดตค่าแคชบางอย่างก่อนจากนั้นฉันจะใช้คุณสมบัติที่คำนวณได้

ความแตกต่างใหญ่: จะเกิดอะไรขึ้นถ้าคุณเรียกฟังก์ชันหรือคุณสมบัติที่คำนวณได้สองครั้ง สำหรับคุณสมบัติที่คำนวณได้ฉันคาดหวังว่า x = property; y = property มีพฤติกรรมเหมือนกับ x = property ทุกประการ y = x ยกเว้นว่ามันอาจทำงานช้าลงเล็กน้อย สำหรับฟังก์ชั่นฉันจะไม่แปลกใจถ้าพฤติกรรมแตกต่างกัน


4

การใช้งานและcountOfAttendeescountOfPaidAttendees()


ตัวแปรที่คำนวณได้คือตัวแปรที่ส่งคืนค่าที่คำนวณได้ทุกครั้งที่เข้าถึง นั่นคือมันไม่ได้เก็บค่า ภายในจะมีการใช้งานเป็นฟังก์ชั่น

ความแตกต่างของฟังก์ชั่นคืออะไร?

  • ความหมายตัวแปรคือสถานะฟังก์ชันคือการดำเนินการ
  • ฟังก์ชั่นควบคุมการเข้าถึงที่เก็บข้อมูลส่วนตัว ตัวแปรจากการคำนวณอาจทำแบบเดียวกันในวิธีกะทัดรัดมากขึ้น ตัวอย่าง
  • ตัวแปรที่คำนวณได้สามารถใช้กับ KVO ส่งผ่านเป็น #keypath และมีสิ่งอำนวยความสะดวกสำหรับการสังเกต: willSet, didSet

คุณควรใช้ตัวแปรเมื่อ

  • มันไม่ได้โยน
  • มันจะส่งกลับคุณสมบัติที่เรียบง่าย
  • มันไม่มีผลข้างเคียงหรือคำกริยาในชื่อของมัน
  • มันเป็น O (1) นั่นคือมันไม่ได้มีค่าใช้จ่ายมากนัก ในตัวอย่างของคุณมันจะเป็น O (n)
  • มันเป็น idempotent การเรียกใช้ที่เหมือนกันหลายครั้งส่งคืนค่าเดียวกันหรือตั้งค่าวัตถุเป็นสถานะเดียวกัน

เหตุผลที่ไม่เกี่ยวข้องที่ต้องการตัวแปรมากกว่าฟังก์ชัน

  • ตัวแปรที่คำนวณช่วยให้คุณไม่พิมพ์ () อย่างไรก็ตามความชัดเจนมีความสำคัญมากกว่าความกะทัดรัดดังนั้นนี่คือข้อโต้แย้งที่อ่อนแอ
  • ตัวแปรอ่านอย่างเดียวสามารถ overriden เป็นอ่าน / เขียน ฟังก์ชั่นระบุว่ามันอ่านได้เสมอเท่านั้น อย่างไรก็ตาม Apple ใช้คุณสมบัติสำหรับตัวแปรแบบอ่านอย่างเดียวเช่น array.count เมื่อมีข้อสงสัยขอให้สอดคล้องกับแพลตฟอร์ม

ทรัพยากร

ตั้งแต่  WWDC 2014 - 204 มีอะไรใหม่ในโกโก้  > 24:40 น. เมื่อใช้ @property

ใช้คุณสมบัติสำหรับสิ่งใดก็ตามที่เกี่ยวกับค่าหรือสถานะของวัตถุหรือความสัมพันธ์กับวัตถุอื่น ผู้สมัครที่ไม่ดี:

  • วิธีการที่ทำสิ่งต่าง ๆ : โหลดแยกวิเคราะห์สลับ…. พวกเขามีคำกริยาในชื่อของมัน
  • เครื่องกำเนิดไฟฟ้า: init, copy, enumerated, …. วิธีการเหล่านี้ไม่ใช่ idempotent
  • วิธีการที่เปลี่ยนสถานะ: nextObject

จาก  สไตล์ Swift โดย Erica Sadun  > คุณสมบัติที่คำนวณได้กับวิธีการ

คุณสมบัติเป็นการแสดงออกถึงคุณภาพโดยธรรมชาติของอินสแตนซ์ในขณะที่วิธีการดำเนินการ

  • วิธีการมีพารามิเตอร์ คุณสมบัติไม่ ชอบวิธีการโทรใด ๆ ที่มีผลข้างเคียง หากวิธีการทำบางสิ่ง (ตัวอย่างเช่นจะโหลดแยกวิเคราะห์สลับหรือพิมพ์) หรือมีชื่อคำกริยามันไม่ควรจะเป็นคุณสมบัติ
  • ต้องการคุณสมบัติสำหรับค่าอย่างง่ายที่คุณสามารถรับและ / หรือกำหนด
  • คุณสมบัติควรแสดงคุณภาพที่แท้จริงของประเภทอินสแตนซ์
  • คุณสมบัติช่วยให้คุณเพิ่มผู้สังเกตการณ์ผ่าน willSet และ didSet ซึ่งแตกต่างจากคุณสมบัติอินสแตนซ์ที่เก็บไว้คุณสมบัติประเภทที่จัดเก็บจะต้องได้รับค่าเริ่มต้นเสมอ

จาก  Kotlin เข้ารหัสประชุม> ฟังก์ชั่น VS คุณสมบัติ ดูคำตอบของแดเนียลดังกล่าวข้างต้น

แหล่งข้อมูลอื่น ๆ ที่ไม่มีข้อมูลที่เกี่ยวข้อง:


3

funcฉันต้องการใช้ การเขียนโปรแกรมเชิงวัตถุทำงานได้ดีโดยไม่มีคุณสมบัติการคำนวณ เนื่องจากคุณได้รับค่าคืนที่ถูกคำนวณ / กรองแล้วบางคนอาจให้เหตุผลว่าคุณสมบัติที่คำนวณได้รู้สึกถูกต้อง แต่นี่คือคำร้องเรียนของฉันถ้าคุณทำอย่างนั้นการอ่านจะได้รับความนิยมเพราะมันให้ความรู้สึกคุ้มค่า

ในบริบทนี้มันไม่สมเหตุสมผลที่จะลองกำหนดค่าที่คำนวณ (และโชคดีที่ IDE ช่วยเราหลีกเลี่ยงสิ่งนี้) แต่ถ้าฉันพยายามกำหนดสิ่งที่คำนวณ แต่ดูเหมือนว่ามีค่า?

event.countOfAttendees = 0; // not possible

ในขณะที่ใช้ func caller know คุณไม่ได้จัดการกับค่าโดยตรง:

event.countOfAttendees()

ฉันคิดว่าถ้ามันเป็นวัตถุพฤติกรรมมันควรจะดูเหมือนว่ามันทำงานมากกว่าที่จะดูเหมือนโครงสร้างข้อมูล หากวัตถุของคุณเป็นใบ้และไม่มีพฤติกรรมใด ๆ แล้วทำไมต้องลองใส่มันลงไป ในกรณีเช่นนั้นคุณอาจแค่มีผู้เข้าร่วมเป็นสาธารณะ

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