之前寫過namespace的問題不過後續都是沒怎麼使用,時下rx,snp…大家都應經不再陌生,也是比較常見的,今天我們結合struct 泛型 class一起看個綜合的例項
通常我們使用名稱空間都是基於一個具體的例項進行的二次封裝(大家公認的)而封裝的載體通常是struct,然後對struct進行extension
背景:
最經在搞protocol buffer來進行資料壓縮,減輕網路流量,於是有了今天的文章
結構定義
在vapor中我們想簡單的返回pb資料不是那麼簡答,因此對返回資料進行了一個包裝
1 返回資料格式
public struct PB<T> : Content where T: Message{
var value: Data
init(_ data: T) throws {
self.value = try data.serializedData()
}
}
複製程式碼
2 request
extension Request{
public func makePB<T>(value: T) throws -> EventLoopFuture<PB<T>> where T: Message{
let result = self.eventLoop.newPromise(PB<T>.self)
let pb = try PB.init(value)
result.succeed(result: pb)
return result.futureResult
}
}
複製程式碼
有定義看到返回的是個基於Message的泛型struct,我們暫時放置於此,後續使用
namespace包裝
1 格式定義
class PBBase<Base, T> where T: Message{
let base: PB<T>
init(_ base: Base) {
self.base = base as! PB<T>
}
}
複製程式碼
2 協議定義
protocol PBProtocol {
associatedtype PBType
associatedtype T: Message
var pb:PBType{get}
}
extension PBProtocol{
public var pb:PBBase<Self, T>{
return PBBase.init(self)
}
}
複製程式碼
完成
extension PB : PBProtocol where T: Message{}
複製程式碼
使用
func testPBBase(){
XCTAssert(pb?.pb.entry != nil, "測試失敗")
XCTAssert(pb?.pb.textFormatString() == bookInfo?.textFormatString(), "測試失敗")
XCTAssert(pb?.pb.textString == pb?.textString, "測試失敗")
}
複製程式碼
我們再來回顧一下整個過程使用了什麼
1 使用 where限定了PBProtocol的使用範圍
2 protocol中associatedtype的綜合使用
2.1 可以定義多個
2.2 可以定義一個具體的型別,也可定義個模糊的型別
複製程式碼
3 nameapce的本質是二次封裝