簡體   English   中英

Swift協議要求屬性作為協議

[英]Swift protocol to require properties as protocol

我試圖定義一個協議“存儲庫”,它需要定義幾個屬性(實現特定協議“DataSource”)

但由於我的真實場景的復雜性,其中一個屬性需要是“DataSource”的子協議。

我把問題簡化為這個簡單的代碼:

protocol DataSource { }

protocol ExtraDataSouce: DataSource {
    func method1() -> String
}

struct MyDataSource: ExtraDataSouce {
    func method1() -> String {
        return "whatever"
    }
}


protocol Repository {
    var firstDataSource: DataSource { get }
    var secondDataSource: DataSource { get }
}

struct MyRepository: Repository {
    var firstDataSource: DataSource
    var secondDataSource: MyDataSource
}

由於“MyRepository”不符合“存儲庫”,因此在編譯時返回錯誤。 但我認為它實際上...有任何想法為什么它不接受定義為“MyDataSource”的“MyRepository”中的“secondDataSource”?

搜索后我找到了關於你的問題的這些信息(如果我在某處錯了或者我錯過了什么,請糾正我):

即使在邏輯上您的代碼應該工作時,當您在MyRepository類中聲明其類型時,swift編譯器也不會分離使用常規或只讀協議變量的情況。 換句話說,如果要在Repository編寫,代碼中的錯誤就會變得很明顯

var secondDataSource: DataSource { get set }

和編譯器不分開這種情況。 我沒有找到完全正確的方法來做你想做的事。 但有兩種接近的方式:

1)顯而易見且可能是最正確的方式 - 在MyRepository更改secondDataSource類型,如果您願意,可以使用其他變量:

var _secondDataSource: MyDataSource
var secondDataSource: DataSource {
        get {return _secondDataSource}
        set {
            guard let newValue = newValue as? MyDataSource else {
                fatalError("MyRepository: attempt to set DataSource type, MyDataSource type expected")
            }
            _secondDataSource = newValue
        }
    }

2)協議方式的關聯類型。 在這里我將改進@RaduNunu的答案,因為他的代碼中的associatedtype type = DataSource行只有占位符效果,並且他的解決方案允許你選擇采用任何類型的secondDataSource ,例如String

protocol Repository {
    associatedtype Type = DataSource
    var firstDataSource: DataSource { get }
    var secondDataSource: Type { get }
}

struct MyRepository: Repository {
    var firstDataSource: DataSource
    var secondDataSource: String // - this is ok!
}

這段代碼將編譯和工作,但看起來很糟糕。 而是鍵入占位符,您最好使用協議一致性:

protocol Repository {
    associatedtype Type: DataSource
    var firstDataSource: DataSource { get }
    var secondDataSource: Type { get }
}

struct MyRepository: Repository {
    var firstDataSource: DataSource
    //var secondDataSource: String - this line not allowed now
    var secondDataSource: MyDataSource
}

此代碼已經非常接近目標。 但是,從現在開始您不能將協議用作關聯類型,因此聲明

var secondDataSource: DataSource

MyRepository中將無法正常工作。 這是使用關聯類型的代價:您只能使用符合DataSource類/枚舉/結構類型。

您的Repository協議實現了DataSource類型的2變量,當您嘗試修改符合Repository協議的struct中的變量類型時,由於所需類型,它不會允許您執行此操作。 您應該使用關聯類型進行此更改

protocol Repository {
    associatedtype type = DataSource
    var firstDataSource: DataSource { get }
    var secondDataSource: type { get }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM