53369


`MyProtocol`を、`enum`のみに準拠させられるようにして、`enum`の`rawValue`を使えるようにすることは可能ですか。  
以下のように`MyProtocol`で`enum`の`rawValue`を使えるようにしたいです。

[code]

    protocol MyProtocol {
    }
    
    enum MyEnum1: String, MyProtocol {
        case a = "AAA1"
        case b = "BBB1"
    }
    
    enum MyEnum2: String, MyProtocol {
        case a = "AAA2"
        case b = "BBB2"
    }
    
    enum MyEnum3: String, MyProtocol {
        case a = "AAA3"
        case b = "BBB3"
    }
    
    class MyClass {
        func methodA(foo: MyProtocol) {
            print(foo.rawValue) // これが出来るようにしたい
        }
    
        func methodB() {
            methodA(foo: MyEnum1.a) // "AAA1"
            methodA(foo: MyEnum2.a) // "AAA2"
            methodA(foo: MyEnum3.a) // "AAA3"
        }
    }
    
[/code]

`MyProtocol`で独自に`rawVal`を定義することで一応やりたいことはできましたが、全ての`enum`で`rawVal`を書く手間が発生するため、できれば`rawValue`をそのまま使いたいです。

[code]

    protocol MyProtocol {
        var rawVal: String { get }
    }
    
    enum MyEnum1: String, MyProtocol {
        var rawVal: String { return self.rawValue }
        case a = "AAA1"
        case b = "BBB1"
    }
    
    class MyClass {
        func methodA(foo: MyProtocol) {
            print(foo.rawVal) // これならできる
        }
    }
    
[/code]

考えをまとめると`enum`にスーパークラスみたいなものを作りたいということなのですが、そもそも`Protocol`の使い方が間違っていますでしょうか……？


CC BY-SA 4.0
2019-03-11T15:01:59.163
53368
2019-03-11T15:25:02.680
23029
question
swift
Protocolをenumだけに準拠させてrawValueを使えるようにすることはできますか。


あなたのご質問内容でよく理解できていない部分もあるのですが、とりあえず「`MyProtocol`で`enum`の`rawValue`を使えるようにしたい」と言うのは普通にこうやれば良いのではないかと言うのを回答の形で書いておきます。

[code]

    protocol MyProtocol {
        var rawValue: String {get}
    }
    
[/code]

これだけで、あなたの前半のコードの残りは全く修正なく、動きます。

[code]

    enum MyEnum1: String, MyProtocol {
        case a = "AAA1"
        case b = "BBB1"
    }
    
    enum MyEnum2: String, MyProtocol {
        case a = "AAA2"
        case b = "BBB2"
    }
    
    enum MyEnum3: String, MyProtocol {
        case a = "AAA3"
        case b = "BBB3"
    }
    
    class MyClass {
        func methodA(foo: MyProtocol) {
            print(foo.rawValue)
        }
    
        func methodB() {
            methodA(foo: MyEnum1.a) // "AAA1"
            methodA(foo: MyEnum2.a) // "AAA2"
            methodA(foo: MyEnum3.a) // "AAA3"
        }
    }
    
    let myObj = MyClass()
    myObj.methodB()
    
[/code]

出力

[code]

    AAA1
    AAA2
    AAA3
    
[/code]

* * *

あるいは下の方法でも、`extension`によるデフォルト実装を使えば、「全ての`enum`で`rawVal`を書く」必要はありません。

[code]

    protocol MyProtocol {
        var rawVal: String { get }
    }
    extension MyProtocol where Self: RawRepresentable, Self.RawValue == String {
        var rawVal: String {
            return self.rawValue
        }
    }
    
    enum MyEnum1: String, MyProtocol {
        case a = "AAA1"
        case b = "BBB1"
    }
    
    class MyClass {
        func methodA(foo: MyProtocol) {
            print(foo.rawVal)
        }
    }
    
[/code]

「`MyProtocol`を、`enum`のみに準拠させられるようにして」と言うのが一体何を言いたいのかよく理解できていませんのでピント外れな回答になっているかもしれませんが、ご質問かコメントでもう少し細部を明らかにしてもらえれば、何かしら答えられることもあるかと思います。


CC BY-SA 4.0
2019-03-11T15:25:02.680
53369
2019-03-11T15:25:02.680
13972
53368
answer