Swift Protocol ความเป็นไปตามข้อกำหนดทางเลือกผ่าน Non-Optional

Aug 18 2020

ฉันมีโปรโตคอลที่มีคุณสมบัติเป็นทางเลือก

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

protocol SomeProtocol {
    var foo: Int? { get }
}

struct StructA: SomeProtocol {
    let foo: Int?
}

struct StructB: SomeProtocol {
    let foo: Int // Type 'StructB' does not conform to protocol 'SomeProtocol'
}

กด Xcode ของ "Fix - คุณต้องการเพิ่มต้นขั้วโปรโตคอลหรือไม่" ปุ่มเพิ่มเวอร์ชันที่เป็นทางเลือกของคุณสมบัติ แต่ตอนนี้โครงสร้างมีชื่อตัวแปรที่ซ้ำกันที่ไม่ถูกต้อง:

struct StructB: SomeProtocol {
    let foo: Int
    var foo: Int? { return foo } // Invalid redeclaration of 'foo'
}

ใน{ get }กรณีนี้ - เท่านั้นฉันสันนิษฐานว่าสิ่งนี้จะ "ใช้ได้ผล" เนื่องจากตัวเลือกที่ไม่เป็นทางเลือกมักจะเป็นไปตามข้อ จำกัด ของทางเลือกซึ่งคล้ายกับวิธีที่คุณสามารถส่งคืนค่าที่ไม่เป็นทางเลือกในฟังก์ชันที่มีประเภทการส่งคืนที่เป็นทางเลือก แต่เห็นได้ชัดว่าไม่เป็นเช่นนั้น

สิ่งนี้ใช้งานได้เหมือนกันสำหรับฟังก์ชั่นเช่นกัน โพรโทคอลfunc bar() -> Int?ไม่เป็นที่พอใจโดยการประกาศประเภทที่สอดคล้องfunc bar() -> Intกัน

มีวิธีแก้ไขปัญหานี้หรือไม่? ฉันไม่ต้องการเปลี่ยนชื่อตัวแปรหรือเพิ่มตัวรับระดับกลาง

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

คำตอบ

pkamb Aug 19 2020 at 00:34

หากโปรโตคอลจัดเตรียมการใช้งานเริ่มต้นที่ส่งคืนตัวเลือก:

protocol SomeProtocol {
    var foo: Int? { get }
}

extension SomeProtocol {
    var foo: Int? { return nil }
}

จากนั้นประเภทที่เป็นไปตามโปรโตคอลสามารถจัดเตรียมตัวแปร / ฟังก์ชันเวอร์ชันที่ไม่เป็นทางเลือกได้:

struct StructB: SomeProtocol {
    let foo: Int
}

ฉันพบสิ่งนี้พูดคุยในฟอรัม Swift Evolution:

ในแวบแรกฉันคิดว่ามีกฎที่อนุญาตให้เราปฏิบัติตามข้อกำหนดของโปรโตคอลด้วยประเภทที่ไม่ใช่ทางเลือก แต่สิ่งนี้ทำให้เกิดข้อผิดพลาด หลังจากการตรวจสอบเพิ่มเติมแล้วฉันสังเกตเห็นว่าต้องมีการใช้งานเริ่มต้นเพื่อที่จะ "แทนที่" ข้อกำหนดด้วยเวอร์ชันที่ไม่เป็นทางเลือก

https://forums.swift.org/t/how-does-this-rule-work-in-regard-of-ambiguity/19448

ทีม Swift นี้ยังกล่าวถึงการอนุญาตประเภทที่ไม่เป็นทางเลือกเพื่อตอบสนองโปรโตคอลที่เป็นตัวเลือกเสริม:

มันสมเหตุสมผลหรือไม่ที่จะอนุญาตให้ตอบสนองความต้องการของโปรโตคอลกับประเภทที่ไม่เป็นทางเลือกเช่นเดียวกับการเริ่มต้นที่ล้มเหลว (อาจมีโปรโมชั่นเสริมโดยปริยาย)

ใช่ทั้งหมด! ยกเว้นส่วนที่สิ่งนี้เปลี่ยนแปลงพฤติกรรมของโค้ดที่มีอยู่ดังนั้นเราจึงต้องระวังให้มาก นี่ถือเป็นส่วนหนึ่งของ[SR-522] ฟังก์ชั่นโปรโตคอลไม่สามารถส่งคืนโควาเรียสได้

ซึ่งติดตามบน Stack Overflow ที่นี่:

เหตุใดข้อกำหนดคุณสมบัติ get-only ในโปรโตคอลจึงไม่สามารถตอบสนองต่อคุณสมบัติที่สอดคล้องได้