[英]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.