簡體   English   中英

Swift Struct with Lazy,私有屬性符合Protocol

[英]Swift Struct with Lazy, private property conforming to Protocol

首先,我有一個協議,只定義了一些readonly屬性,例如:

protocol Example {
  var var1:String { get }
  var varArray:[String] { get }
}

然后我想創建一個符合該協議的結構。 我遇到的問題是,我有兩個相互矛盾的要求:

  1. 屬性需要延遲生成。
  2. 屬性是相關的,需要一起生成。

我似乎找不到辦法做到這一點。 我最接近的是這樣的:

struct AStruct : Example {
  private lazy var data:(var1:String, varArray:[String]) = {
    var stringValue:String = ""
    var stringArray:[String] = []
    //Generate data
    return (stringValue, stringArray)
  }()

  var var1:String {
    return self.data.var1
  }

  var varArray:[String] {
    return self.data.varArray
  }
}

問題是,我收到錯誤: Immutable value of type 'AStruct' only has mutating members named 'data'

有誰知道我可以實現目標的方式? 從技術上講, data變量是可變的,但永遠不會改變。 我不能使用letlazy ,所以我不能指定一旦它被創造的價值永遠不會改變。 我需要生成值,因為struct是在主線程上創建的,但是值將由后一個進程完全在后台線程上生成。

更新

所以有人向我指出,我可以讓getter在協議和結構中都發生mutating 這是有效的,除了我現在有一個問題,我不能在任何其他結構(我是)中使用此結構。 所以最后,我把問題推到另一個結構中,我不想讓它變成可變的。

例如:

struct Container {
  let astruct:AStruct
  let callback:() -> ()
}

我無法從Container訪問AStruct的變量,因為Container是不可變的, AStruct的成員變量是變異的。 試圖訪問它們給了我之前提到的相同的錯誤消息。

將容器更改為使用var而不是let產生相同的錯誤:

struct Container {
  var astruct:AStruct
  let callback:() -> ()
}

如果我在處理類中設置一個函數來接收要處理的Container

func processContainer(cont:Container){
  self.doSomething(cont.astruct.var1)
}

我得到了同樣的錯誤: Immutable value of type 'AStruct' only has mutating members names 'sql'

因為訪問惰性data變量會改變AStruct ,所以對它的任何訪問都必須標記為也會改變結構。 所以你需要寫:

struct AStruct : Example {
    // ...
    var var1: String {
        // must declare get explicitly, and make it mutating:
        mutating get {
            // act of looking at data mutates AStruct (by possibly initializing data)
            return self.data.var1
        }
    }

    var varArray:[String] {
        mutating get {
            return self.data.varArray
        }
    }
}

但是,你現在會發現Swift抱怨你不符合Example ,因為它的get var1沒有被標記為變異。 所以你必須改變它以匹配:

protocol Example {
    var var1:String { mutating get }
    var varArray:[String] { mutating get }
}

所以我想詳細說明我最終遵循的解決方案。 事實證明,我認為Swift目前無法實現我的目標。 一旦你開始mutating get道路,它最終會級聯到太多區域(所有容器結構都需要變異等)。 最后,這種破壞了我想首先使用結構的全部原因。

也許在未來的道路上Apple會添加一個lazy let var = ... 這將通過保證延遲變量只設置一次來確保不變性......只是不立即。

所以我的解決方案只是完全放棄structs並使用classes來代替。 我保持類在功能上不可變,所以我仍然保留它。 從字面上看,我所要做的就是將struct更改為class ,現在懶惰的構造工作完美,我的所有問題都消失了......除了我正在使用類。

總而言之,@ AirspeedVelocity有一個正確的解決方案,即使我的需求難以為繼,所以我會接受他的解決方案。 我剛剛離開這里,所以其他人可以理解我是如何克服這個問題的...使用類。

暫無
暫無

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

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