32282

[code]

    enum Optional2<T> : ExpressibleByNilLiteral {
        case None
        case Some(T)
        init(){
            self = .None
        }
        init(_ some: T){
            self = .Some(some)
        }
        init(nilLiteral: ()){
            self = .None
        }
    }
    
[/code]

  
let v1 : Optional2 = 10 // ERROR  
let v2 : Optional2 = Optional2(10) // OK  
let v3 : Optional2 = Optional2.Some(10) // OK  
let vnl : Optional2 = nil // OK

上記のERRORは、本当のオプショナル型の場合、代入できますが、  
上記の列挙型では、コンパイルエラーとなります。  
代入演算子を作成しようと思ったのですが、実装に失敗します。  
static func = (lhs: Optional2 , rhs: T)->Void{}


CC BY-SA 3.0
2017-01-30T09:50:24.793
32256
2017-01-31T12:10:16.203
11148
question
swift swift3
Optional型(列挙型)へ値を代入


_**`let v1 : Optional2 = 10 // ERROR` を解決する方法があるのでしょうか？**_

ありません。

* * *

「`Optional`型の実態はこのようなenum型です」と言う解説をどこかで見つけられて、「それなら同じ構造を持つenum型を定義すれば、`Optional`型と同じ動作をさせることができるのか?」と言う疑問を持たれてお試しなのだと思いますが、結論は上記の通りです。

あなたが _**`ERROR`**_
と示された例(が動いたとしたら)では`T`型が自動的に`Optional2<T>`型に変換されているわけですが、このような動作は本物の`Optional`型に特有のもので、同内容のenum型を定義しても同じ動作は起こりません。Swift言語の開発スタッフはこのような状況をcompiler
magicと呼んでいましたが、日本語の語感に合わせて言い換えると「`Optional`型はSwiftコンパイラーから特別扱いを受けている」と言った方が良さそうです。

[Swift
4での文字列型のあり方について論じたこの文書](https://github.com/apple/swift/blob/master/docs/StringManifesto.md)の中では、

> `Int` is a subtype of `Optional<Int>`

と表現している部分があるのですが、もちろんSwiftの言語上の機構としてはサブタイプと言う概念はなく、コンパイラー内部の問題か、もしくはコンパイラー製作者の概念の問題で、Swift言語を使うプログラマーがデータ型間にサブタイプの関係を定義できるわけではありません。コンパイラーが`Optional`型を特別扱いして、「サブタイプ」と呼びたくなるような動作を実現しているわけです。

他にも自前の`Optional`風データ型を`if-let`などのOptional-bindingで使えるようにする方法もありません。

**`Optional`型の基本的な構造はenumだが、その様々な振る舞いはコンパイラーの特別扱い(compiler magic)によって成り立っている**

とご理解ください。

* * *

なお、Swiftでは代入演算子`=`はユーザ定義不可なので、代入演算子のオーバーロードによって解決することもできません。


CC BY-SA 3.0
2017-01-31T12:10:16.203
32282
2017-01-31T12:10:16.203
2020-06-17T08:14:45.997
-1
13972
32256
answer