web-dev-qa-db-ja.com

Enum init?(rawValue:String)をオーバーライドしてオプションにしない

Swiftの列挙型のrawValueからinitを取得して、rawValue initがnilを返す場合にデフォルト値を返します。現在、次のようなものがあります。

public init(fromRawValue: String){
        self = Language(rawValue: fromRawValue) ?? .English
}

これは完全に新しい初期化子であるため、これは好きではありません。私はこのようなものを作ろうとしました:

public init(rawValue: String){
        self = Language(rawValue: fromRawValue) ?? .English
}

しかし、アクセスが悪いランタイム例外があります。どういうわけかそれを機能させることができますか、またはこの新しいものを使用する必要があり、元のオプションをオーバーライドしてオプションではありませんか?

失敗可能なものを使用している完全に新しいもので回避策ではないrawValueからの元のinitをオーバーライドできるかどうかを知りたいです。

44
Prettygeek

デフォルトの初期化子はfailableです。これは、受け取ったパラメーターが有効な列挙型のケースと一致しない場合、nilを返すことを意味します。

今、あなたは2つの互換性のないことをしたい:

  1. redefineをデフォルトの初期化子にして、失敗しないようにします。実際には、受信したパラメーターが無効な場合にデフォルトの列挙値を作成する必要があります。
  2. 再定義されたイニシャライザ内で、新しいイニシャライザと同じ名前を使用して、フェイル可能なイニシャライザ(もはや存在しない)を呼び出します。

これは不可能です。次の3つの解決策があります。

1)別の初期化の作成

デフォルト値、異なるパラメータ名を使用して、フェイル不可の新しいイニシャライザを定義し、その内部でデフォルトのフェイル可能イニシャライザを呼び出します。

enum Language: String {

    case english = "English", italian = "Italian", french = "French"

    init(fromRawValue: String){
        self = Language(rawValue: fromRawValue) ?? .english
    }
}

2)デフォルトの初期化の再定義

デフォルトのイニシャライザを再定義し、失敗しないようにし、その中に完全なロジックを記述します。

enum Language: String {

    case english = "English", italian = "Italian", french = "French"

    init(rawValue: String) {
        switch rawValue {
        case "Italian": self = .italian
        case "French": self = .french
        default: self = .english
        }
    }
}

3)静的関数の作成

enum Language: String {

    case english = "English", italian = "Italian", french = "French"

    static func build(rawValue: String) -> Language {
        return Language(rawValue: rawValue) ?? .english
    }
}

これで、Language値を作成できます。

let italian = Language.build(rawValue: "Italian") // Italian
let defaultValue = Language.build(rawValue: "Wrong input") // English
102
Luca Angeletti

デフォルトのinitを再定義するためのLucaのソリューションに加えて、rawValueパラメータータイプをオプションにすることもできます。これにより、データソースが信頼できない場合に呼び出しサイトの一部のコードが削減されます。

enum PrecipitationType: String {
    case rain, snow, sleet, none

    typealias RawValue = String

    init(rawValue: String?) {
        guard let rawValue = rawValue else { self = .none; return }

        switch rawValue {
            case PrecipitationType.rain.rawValue: self = .rain
            case PrecipitationType.snow.rawValue: self = .snow
            case PrecipitationType.sleet.rawValue: self = .sleet
            default: self = .none
        }
    }
}

最初にこれを試したとき、複数のエラーが生成されました。キーは、RawValue typealiasを再定義して、RawRepresentableへの準拠を維持することでした。

5