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

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

ただいまの
回答率

87.79%

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

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 573

score 204

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の記法に関する記事が見当たらなかったため、ご存知の方がいればお力添えを願います。
よろしくお願い申し上げます。

enum Rank: Int {
    case ace = 1
    case two, three, four, five, six, seven, eight, nine, ten
    case jack, queen, king

    func simpleDescription() -> String {
        switch self {
        case .ace:
            return "ace"
        case .jack:
            return "jack"
        case .queen:
            return "queen"
        case .king:
            return "king"
        default:
            return String(self.rawValue)
        }
    }
}

if let convertedRank = Rank(rawValue: 3) {
    let threeDescription = convertedRank.simpleDescription()
}
//以下のコードは a swift tourにはないです
print(threeDescription)//3
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+2

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

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

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

たとえば

enum R: Int {
  case a
}


はコンパイラにより

enum R: RawRepresentable {
  case a

  typealias RawValue = Int
  var rawValue: Int
  init?(rawValue: Int) {
    if rawValue == 0 {
      self = .a
    } else {
      return nil
    }
  }
}


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

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


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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/11/13 23:28

    コメントありがとうございます。なんとなく特殊である仕様はご提示いただたイニシャライザからぼんやり理解できました。しかしながら「判別するだけで・・わけではありません」のくだりが少しわからないのですが

    判別とはまさに
    if rawValue == 0
    で受け取ったrawValueを判別に利用していると思われますが
    その結果、trueであれば
    self = .a
    というのが少しわかりませんでした。
    例えば実際のコードで
    Rank(rawValue: 3)であれば、nilになる
    (rawValue: 0)であればself = .aとしてどうなるのでしょうか?
    ※self.propertyではなくselfだけに代入する場合swiftは何を指すのか理解ができていないことが原因かもしれません、おそらく定義した列挙型をのものを指していると思われますが、列挙型に.aを代入する?という思考の状況です・・・

    度々申し訳ございませんが、よろしくお願い申し上げます。

    キャンセル

  • 2020/11/13 23: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) としているのは、コメントをベースに考えるとおそらく何かを判別するためにこの様な記述をしているということでしょうか?

    よりわかりづらくさせてしまっていたら申し訳ございません。
    よろしくお願い申し上げます。

    キャンセル

  • 2020/11/14 08:52

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

    キャンセル

  • 2020/11/15 14:44

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

    キャンセル

0

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

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/11/13 17:23

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

    キャンセル

0

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

型名(rawValue: xxx)


になります。

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/11/13 17: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 //イメージ的にこういうことですか?

    よろしくお願い申し上げます。

    キャンセル

  • 2020/11/13 19: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がつきますが)。

    キャンセル

  • 2020/11/13 23: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の値として順番に割り当てられているのではないでしょうか?

    考えながらお尋ねはしているのですが、少し的外れなことを申し上げていたら申し訳ございません。
    よろしくお願い申し上げます。

    キャンセル

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

  • ただいまの回答率 87.79%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る