この質問見た瞬間おもしろいと思ったので調べてみました。
まずはコードから
swift
1
2let value: Int = 150
3
4class Shadowing {
5
6 let value: Int? = 100
7
8 init() {
9 let value = value //エラー
10 if let value = value {
11 print(value) //
12
13 print(self.value)
14 }
15 print(value)
16 }
17
18}
19
上記の例だとInt?型の定数value
とif-let構文中の定数value
の名前が同じですよね。このように同じ名前のものを使う事をシャドーイングと言うそうです(今初めて名前を知りました。シャドーイングを言いたいだけちゃうんかと言うツッコミは受け付けません)。
そして質問内容の
Int?型の変数aがあっても、if-letのところでInt型のaを新しく宣言してもよく
これはYesです。ただし質問に書かれてるInt型のaもInt?型のaも変数ではなく定数です。変数はvar
です。
ifの中ではInt型のaが優先的に使われるということでしょうか?
これは優先的というよりもif-let構文内で定数aと言えばInt型のaの事を指します。self.aとするとInt?型のaを指します。この辺はスコープの問題とも絡んできますね。
なので勘違いはほとんどなく理解に問題ないんじゃないでしょうか。
(追記)
tyobigorouさんのコメントを受けて修正します。
Swiftはオプショナルバインディング中でのシャドーイングが可能になっています。これは例外として出来ることで通常シャドーイングは出来ないようになっていそうです。もしかしたらやり方があるかもしれませんが自分の調べた結果ではオプショナルバインディング中のみでした。SwiftはHaskellに影響を受けていると聞いたことがあり、そのHaskellでもシャドーイングが可能です。そしてHaskellではシャドーイングが出来る範囲もSwiftよりも広いようです。
そしてそのシャドーイングの効果ですが代入する値を特定スコープ内で使えなくする、という効果です。だから上記の例でメンバ定数であるvalueはif-let構文のブロック中では直接呼び出せなくなっていてvalueを呼び出すとif-let構文の条件で宣言された定数valueが呼び出される、ということのようです。
余談
swift
1class Shadowing {
2
3 let value: Int? = 100
4
5 init() {
6 if let value = value {
7 print(value) // 100
8 let value = 150
9 print(value) //150
10 print(self.value) // Optional(100)
11 }
12 print(value) //Optional(100)
13 }
14
15}
何故かこれが許される・・・。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/08/25 11:58
2018/08/25 12:16 編集
退会済みユーザー
2018/08/25 13:42 編集
2018/08/25 14:35 編集
2018/08/25 15:49
2018/08/26 00:17
2018/08/27 01:14 編集
2018/08/27 05:30
2018/08/28 18:13
2018/08/29 05:50 編集
退会済みユーザー
2018/08/29 05:12 編集
2018/08/29 05:52 編集
退会済みユーザー
2018/08/29 07:43 編集
2018/08/29 07:29
2018/08/29 09:13