簡體   English   中英

沒有初始化程序但具有屬性觀察器的Swift類

[英]Swift class with no initializers but with property observer

我剛剛開始學習敏捷,對類初始化器有疑問。 這是我的示例代碼:

struct Resolution {
  var width = 0
  var height = 0
}

let someResolution = Resolution()

class TV {
  var res: Resolution! {
    didSet {
      res.width = 1
      res.height = 1
    }
  }
}

var television = TV()
var resolution = Resolution()
television.res = resolution

我正在嘗試使用屬性觀察器。 當我隱式打開結構的屬性觀察器類型時,一切正常。 否則,它說“類沒有初始化程序。我很困惑為什么我應該隱式解開結構。在此先感謝!

您的問題尚不完全清楚,但是我想您是在問為什么不能替換這個問題:

var res: Resolution! {

…有了這個:

var res: Resolution {

您的線索來自完整的編譯器錯誤消息,您可以通過查看編譯器日志(如果您在操場上,則可以在操場上控制台)中查看:

error: class 'TV' has no initializers
class TV {
      ^
note: stored property 'res' without initial value prevents synthesized initializers
  var res: Resolution {
      ^
error: 'TV' cannot be constructed because it has no accessible initializers
var television = TV()

當屬性的類型為Resolution! ,您是說:“它可能為零,但是如果有人嘗試在它為零時讀取它,那將是一場可怕的災難,我的整個應用程序都將崩潰。”因此,Swift將TVres設置為nil進行初始化,並希望您能夠立即將其設置為其他內容。

但是,當屬性的類型為Resolution ,您說的是:“即使從沒有人看,它也永遠不會為零,永遠不會,甚至永遠不會。”這意味着從實例化TVres 必須具有一個值。 但是那個值應該是多少? 沒有默認設置。 如果類型為Resolution則有兩個選擇:

  1. 使用屬性初始值設定項將其設置為一些默認值(這就是您要嘗試執行的操作):

      class TV { var res: Resolution = Resolution(width: 1, height: 1) } 

    …或使用初始化程序,您可以讓Swift推斷類型:

      class TV { var res = Resolution(width: 1, height: 1) } 
  2. 在實例化該類時,請問創建TV人指定初始值:

     class TV { init(res: Resolution) { self.res = res } var res: Resolution { didSet { res.width = 1 res.height = 1 } } } var resolution = Resolution() var television = TV(res: resolution) 

除了:所有這些絕對沒有意義 ,因為在設置分辨率后,您立即將width&height更改為1(是什么?!),但是它確實可以編譯。

這樣,來自編譯器的“合成的初始化器”消息就會出現? Swift會自動為您的類創建一個空的init() ,它不會執行任何操作,但是如果有任何非可選屬性要初始化,則不會執行任何操作。 如果有,則必須編寫自己的初始化程序。

(請注意,如果TV是結構,則Swift 為您生成該init(res:) 。它與結構有關,但與類無關。)

第三種選擇是使類型為Resolution?

class TV {
  var res: Resolution? {
    didSet {
      res?.width = 1
      res?.height = 1
    }
  }
}

這是比Resolution!更好的選擇Resolution! ,這只是一場等待發生的崩潰。 隱式解開的可選對象只能是不得已而為之,這是在非常具體,經過仔細考慮的情況下使用的。

在初始化時間結束之前,每個實例變量都必須具有一個值。

  • 如果您不使用Optional,那么您必須在此處提供一個實際的Resolution實例作為res的值,而您並沒有這樣做。

  • 如果確實使用Optional,則編譯器會提供nil作為值,因此可以滿足對值的需要。

一種可能是這樣編寫您的類:

電視類{var res = Resolution(){didSet {res.width = 1 res.height = 1}}}

現在res具有一個初始值:即一個實際的Resolution實例。

但是你在做什么並沒有錯 當您知道無法在初始化時為實例變量提供值,但是打算在此后不久提供一個值時,通常使用Optional即可。

暫無
暫無

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

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