質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

3回答

1256閲覧

enum型(rawValue: int)の記法の意味を教えてください

pegy

総合スコア245

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2020/11/13 07:47

a swift tour のenum型の説明において、以下の説明とコードの例示があります。

By default, Swift assigns the raw values starting at zero and incrementing by one each time, but you can change this behavior by explicitly specifying values. In the example above, Ace is explicitly given a raw value of 1, and the rest of the raw values are assigned in order. You can also use strings or floating-point numbers as the raw type of an enumeration. Use the rawValue property to access the raw value of an enumeration case.

Use the init?(rawValue:) initializer to make an instance of an enumeration from a raw value. It returns either the enumeration case matching the raw value or nil if there is no matching Rank.

純粋に文章通り、読むとrawValue1が明示的に与えられていて、残りのrawValueは順番に割り当てられる。init?(rawValue:)でインスタンスを作成するとraw valueに一致するenum型または一致するものがなければnilを返します。
と要点を解しております。

ここで、Rank(rawValue: 3)の記法が全く文章からは理解できないのですが、何をしようとしているのでしょうか?文章にもある様なinit?にもなっていないですし、またそこが理解できてないため最終的になぜthreeDescriptionが3を返すのかという動作の過程が理解できません。

意外とのこの様なenumの記法に関する記事が見当たらなかったため、ご存知の方がいればお力添えを願います。
よろしくお願い申し上げます。

Swift

1enum Rank: Int { 2 case ace = 1 3 case two, three, four, five, six, seven, eight, nine, ten 4 case jack, queen, king 5 6 func simpleDescription() -> String { 7 switch self { 8 case .ace: 9 return "ace" 10 case .jack: 11 return "jack" 12 case .queen: 13 return "queen" 14 case .king: 15 return "king" 16 default: 17 return String(self.rawValue) 18 } 19 } 20} 21 22if let convertedRank = Rank(rawValue: 3) { 23 let threeDescription = convertedRank.simpleDescription() 24} 25//以下のコードは a swift tourにはないです 26print(threeDescription)//3

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

この件はちょっとややこしいのです。

まず、Intなどを継承/適合しているように見えるenumは実際はIntなどを継承していません。
これらのenumが実際に適合しているのはRawRepresentableというprotocolです。
AppleのRawRepresentableのリファレンスページ

このprotocolにはrawValueというプロパティとinit?(rawValue: Self.RawValue)というイニシャライザが宣言されています。
enumをIntなどを継承/適合しているように宣言すると、コンパイラが自動的にこの2つを実装しRawRepresentableプロトコルに適合させます。

たとえば

swift

1enum R: Int { 2 case a 3}

はコンパイラにより

swift

1enum R: RawRepresentable { 2 case a 3 4 typealias RawValue = Int 5 var rawValue: Int 6 init?(rawValue: Int) { 7 if rawValue == 0 { 8 self = .a 9 } else { 10 return nil 11 } 12 } 13}

と同じようなのものになります。(このコードはコンパイルできません。また、rawValueはstored propertyとはなっていないです。)
Intなどを継承/適合しているように見える記法を使わないとSwiftで書けないのでちょっとズルをしている、といえばいいでしょうか。
そのためstructやclassに比べて直感的ではなくなっています。
僕の書いた仮想的なコードのイニシャライザを見てもらえばわかりますが、初期化にrawValueを渡してはいますが、それはどのcaseであるかを判別するために使用するだけで値そのものが保存されるわけではありません。

これで疑問が解けるのではないでしょうか。


この回答には嘘が含まれていますが、これをつまびらかにするにはローレベルな知識が必要になります。
Swiftという言語を学ぶのにそこまでする必要とないと思いますので「そういうもの」で納得してください。

投稿2020/11/13 09:18

編集2020/11/13 09:31
MasakiHori

総合スコア3391

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pegy

2020/11/13 14:28

コメントありがとうございます。なんとなく特殊である仕様はご提示いただたイニシャライザからぼんやり理解できました。しかしながら「判別するだけで・・わけではありません」のくだりが少しわからないのですが 判別とはまさに if rawValue == 0 で受け取ったrawValueを判別に利用していると思われますが その結果、trueであれば self = .a というのが少しわかりませんでした。 例えば実際のコードで Rank(rawValue: 3)であれば、nilになる (rawValue: 0)であればself = .aとしてどうなるのでしょうか? ※self.propertyではなくselfだけに代入する場合swiftは何を指すのか理解ができていないことが原因かもしれません、おそらく定義した列挙型をのものを指していると思われますが、列挙型に.aを代入する?という思考の状況です・・・ 度々申し訳ございませんが、よろしくお願い申し上げます。
pegy

2020/11/13 14:36

別視点で混乱の原因なのかもしれませんが、例えば最終的にhreeDescriptionで3を出力したいのであれば、下段の処理でRank(rawValue: 3) なんてする必要がない様に思えます。なぜなら原文通り、threeには順番通りrawValueの3が割り当てられているからです。 if let convertedRank = Rank(rawValue: 3) { let threeDescription = convertedRank.simpleDescription() print(threeDescription) } ----------------------------------------------------------------- let convertedRank = Rank.three let threeDescription = convertedRank.simpleDescription() print(threeDescription) なので、ここでわざわざRank(rawValue: 3) としているのは、コメントをベースに考えるとおそらく何かを判別するためにこの様な記述をしているということでしょうか? よりわかりづらくさせてしまっていたら申し訳ございません。 よろしくお願い申し上げます。
MasakiHori

2020/11/13 23:52

おそらくあなたは何がわかってないかが整理できてないです。 もうちょっと自分で考えてみましょう。
pegy

2020/11/15 05:44

ご指摘ありがとうございます。確かに混乱中で整理できていない点はその通りです。少し落ち着いて考えてみようと思います。
guest

0

rawValueがあるenumの場合、rawValueからenumを作るためのイニシャライザが自動的に作成されます。それが、

swift

1型名(rawValue: xxx)

になります。

残念ながら、リファレンスマニュアルを読んでも明確な書き方がされていないようですが、
Raw ValuesのInitializing from a Raw Valueのあたりを読んでみてください。

投稿2020/11/13 08:21

AOKINAO

総合スコア268

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pegy

2020/11/13 08:34

ありがとうございます。今並行して該当箇所を読んでいるのですが、どうしてもピンとこない部分があるので、一点だけお尋ねさせてください。イニシャライズしていることはわかるのですが、例えばclassで class sample { var name: String init (name:String) { self.name = name; } } let test = sample ("Mark":String) であれば、var nameを初期化しており、nameに"Mark"を割り当てている過程が理解できます。 一方、Rank(rawValue: 3) はどこにどうやって3を割り当てているのでしょうか? enum Rank: Int { case ace = 1 case two case three = 3 //イメージ的にこういうことですか? よろしくお願い申し上げます。
AOKINAO

2020/11/13 10:55

そうです。pegyさんが訳しているとおり、「rawValue1が明示的に与えられていて、残りのrawValueは順番に割り当てられる」ので、aceに1が明示的に与えられていて、残りは順番に割り当てられ、threeが3になります。 わかりにくいのは、classやstructは、変数が内包しているプロパティにイニシャライザの引数が代入される(または、引数を利用してプロパティを初期化する)のに対して、enumは変数そのものがrawValueから初期化されると云うことです。 ですから、 var sample = Sample(name: "x") の場合は sample.name = "x" となりますが、 var convertedRank = Rank(rawValue: 3) の場合は、 convertedRank = Rank.three と同様になります(正確には、Optionalがつきますが)。
pegy

2020/11/13 14:15

コメントありがとうございます。少し混乱中です。。。optionalかどうかは別として var convertedRank = Rank(rawValue: 3) convertedRank = Rank.three print(convertedRank!.rawValue) //3 ------------------------------------------------- convertedRank = Rank.three print(convertedRank.rawValue) //3 どちらも3が返ってきます。 推察するに、Rank(rawValue: 3)なんて初期化で3を格納しなくても元々原文通り3はcase threeの値として順番に割り当てられているのではないでしょうか? 考えながらお尋ねはしているのですが、少し的外れなことを申し上げていたら申し訳ございません。 よろしくお願い申し上げます。
guest

0

Rank(rawValue: 3)の記法が全く文章からは理解できないのですが

enum Rankのイニシャライザ、要するにinit?(rawValue:)のことです。

(enumに限ったことではありません。インスタンスを生成するときは型名()でその型のイニシャライザを呼びます)

投稿2020/11/13 08:06

編集2020/11/13 08:09
ozwk

総合スコア13553

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pegy

2020/11/13 08:23

ありがとうございます。仮にRank(rawValue: 3)がイニシャライザであるとすればRank(rawValue: 3)はどの様に動作をしているのでしょうか?(どのプロパティに3を割り当てている?というのが正しいかはわからないので動作と表現しております)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問