2016-11-28 3 views
0

今、私は多くのオプションのプロパティを持つクラスを扱っています。これらのオプションのプロパティのいくつかについては、さまざまな型を取り入れて、基本的にはフードの下にそれらを型として保存したいと思っています。例えば、ユーザはDateStringまたはIntを指定して、特定の日付を示すことができます。ここに私がしようとしているものの例があります。 (私は潜在的に危険なラッピングをやっているという事実を無視します。)あいまいなオプションの引数が異なる型を持つ場合のSwift初期化子

class SOExample { 
    let value: Int 
    let time: Double? 

    init(value: Int, time: Double? = nil) { 
     self.value = value 
     self.time = time 
    } 

    convenience init(value: Int, time: Int? = nil) { 
     if time != nil { 
      self.init(value: value, time: Double(time!)) 
     } else { 
      self.init(value: value, time: nil) 
     } 
    } 
} 

私は任意のoptionalsせずに初期化しようとすると、問題が来る - それは使用するためにどのような初期化子を知りません。例えば、SOExample(value: 7)は、ユニットテストでは、このバックを与える:

error: ambiguous use of 'init(value:time:)' 
     let soExample = SOExample(value: 7) 
         ^
<unknown>:0: note: found this candidate 
<unknown>:0: note: found this candidate 
<unknown>:0: error: build had 1 command failures 

は、どのように私は私がやろうとしている何をすることができるだろうか?私はこれについて完全に間違った方法をとっていますか?これを行うには、複数のイニシャライザ以外のものを使用する必要がありますか?

+1

あなたは単なる入力から不要なパラメータを削除できますか? –

+1

もっと理にかなった例を表示できますか?あなたは 'nil'値をアンラップし、' fooDouble:Int'は明らかではないのでコードがクラッシュします。 – luk2302

+0

@EugeneZhenyaGordinがトリックをやった!今私はこれを求めて愚かな気分になります。それを回答として投稿してください。 – TheSoundDefense

答えて

0

、この問題はconvenience init初期化子上の任意の成分を除去することによって解決することができます。 timeパラメータがIntであるときにのみ、そのイニシャライザを呼び出すことが必要な場合は、変数がその特定のものに必要になるはずです。initこれは、この場合のあいまいさを解決します。

class SOExample { 
    let value: Int 
    let time: Double? 

    init(value: Int, time: Double? = nil) { 
     self.value = value 
     self.time = time 
    } 

    convenience init(value: Int, time: Int) { 
     self.init(value: value, time: Double(time)) 
    } 
} 

これは最終的にそれが解決できない曖昧のように見えるので、私は、しかし、パラメータの型としてInt?を使用することはできません。とにかく私のアプリケーションのために十分に機能するので、それを強制することもあります。

1

init関数のいずれかで不要なパラメータを削除することで、この問題を解決できます。

0

問題を解決する最も簡単な方法は、簡易メソッドで2番目のパラメータの名前を変更することです。問題を引き起こすnilを渡すと、2つの初期化メソッドのシグネチャは同じになります。これがあなたの事件を処理するかどうかはわかりません。二つの方法の署名が同じであり、あなたは、静的メソッドを作成することができ、異なるタイプとゼロのデフォルト値と二番目のパラメータに同じラベルを使用できないことを考えると

class SOExample { 
let value: Int 
let time: Double? 

init(value: Int, time: Double? = nil) { 
    self.value = value 
    self.time = time 
} 

convenience init(value: Int, timeAsInt: Int? = nil) { 
    if timeAsInt != nil { 
     self.init(value: value, time: Double(timeAsInt!)) 
    } else { 
     self.init(value: value, time: nil) 
    } 
} 

}

あなたのクラスにはAnyのタイプがあり、可能な場合を処理します。

class SOExample { 
    let value: Int 
    let time: Double? 




    init(value: Int, time: Double? = nil) { 
     self.value = value 
     self.time = time 
    } 

    static func make(value: Int, time: Any? = nil) -> SOExample { 

     if time != nil { 

      // Int 
      if let timeInt = time as? Int { 
       return SOExample(value: value, time: Double(timeInt)) 
      } 

      // String 
      if let timeString = time as? String { 
       if let timeDouble = Double(timeString) { 
        return SOExample(value: value, time: timeDouble) 
       } 
      } 
     } 

     return SOExample(value: value) 
    } 
} 

次にあなたがそうのようにそれを使用します。ユージンジェーニャゴードンによって示唆されるように

let exampleOne = SOExample.make(value: 4, time: 4) 
let exampleTwo = SOExample.make(value: 4, time: "4") 
関連する問題