2015-05-25 23 views
5

我在Swift中創建了一個單元框架,它具有用於不同單元(如質量和體積)的度量超類和子類。一個特性是允許框架正確地猜測它創建的單元並返回正確的類。示例代碼:使超類的初始化器返回一個特定的子類?

class Measurement { 
    var unitString : String 
    init(unknownUnit: String) { 
     // checks if the unit is either Volume or Mass, and returns an instance of that class 
    } 
} 

class Volume : Measurement { 
    init(unitString: String) { 

    } 
} 

class Mass : Measurement { 
    init(unitString: String) { 

    } 
} 

let mass = Mass("kg")     // class: Mass 
let volume = Volume("ml")    // class: Volume 
let shouldBeVolume = Measurement("ml") // class: Volume 
let shouldBeMass = Measurement("kg") // class: Mass 

是否有可能有初始化時,它繼承的類創建一個特定的子類的對象?

圖書館被命名爲Indus Valley和開放源代碼在GitHub上

+0

這絕對是斯威夫特的一個惱人的限制'init'沒有返回值。 – pkamb

回答

0

它的玩弄與傳承具有父類知道它的子類(非常差的反模式!),但是這會工作...

class Measurement { 
    var unitString : String 

    class func factory(unknownUnit: String) -> Measurement { 
     if unknownUnit == "kg" { 
      return Mass(myUnit: unknownUnit) 
     } else { // Random default, or make func return Measurement? to trap 
      return Volume(myUnit: unknownUnit) 
     } 
    } 

    init(myUnit: String) { 
     // checks if the unit is either Volume or Mass, and returns an instance of that class 
     self.unitString = myUnit 
    } 
} 

class Volume : Measurement { 
} 

class Mass : Measurement { 
} 

let mass = Mass(myUnit: "kg")     // class: Mass 
let volume = Volume(myUnit: "ml")    // class: Volume 
let shouldntBeVolume = Measurement(myUnit: "ml") // class: Measurement 
let shouldntBeMass = Measurement(myUnit: "kg") // class: Measurement 
let isVolume = Measurement.factory("ml") // class: Volume 
let shouldBeMass = Measurement.factory("kg") // class: Mass 
1

如果你在超類中創建子類對象,那麼你的應用程序將會崩潰,因爲調用init方法將是遞歸的。爲了測試你可以創建一個類的層次結構並嘗試在超類中創建子類對象。

你可以通過使用面對面的設計模式來解決這個問題。只需要創建一個內部使用所有其他類並創建該對象並返回的Interface類。

class UnitConverter { 
    class func measurement(unknownUnit: String) -> Measurement { 
     if unknownUnit == "kg" { 
      return Mass(unknownUnit) 
     } else if unknownUnit == "ml" { 
      return Volume(unknownUnit) 
     } 

     return Measurement(unknownUnit) 
    } 
} 
+0

只有在子類調用父類的* same *初始值設定項時,情況纔是如此。但是,如果子類調用超類的特殊(如私有)初始值設定項,它將不會無限遞歸。這就是它在Obj-C中的工作原理。 – devios1

1

根據不同的使用情況,也許這可能是一個合適的替代品:

enum Measurement { 
    case Mass 
    case Volume 

    static func fromUnit(unit:String) -> Measurement? { 
     switch unit { 
      case "mg", "g", "kg": return Mass 
      case "ml", "dl", "l": return Volume 

      default: return nil 
     } 
    } 
} 
+0

是的,這是我目前的解決方案,想知道如果任何人有任何初始化程序:) – hakonbogen