目次

目次

【Swift】enumとstatic let(型プロパティ)による定数定義

アバター画像
長島大和
アバター画像
長島大和
最終更新日2023/07/21 投稿日2023/07/21

はじめに

こんにちは。株式会社レコチョクの長島です。 2022年4月に新卒で入社し、NX開発推進部iOSアプリ開発グループに所属しています。 最近聞いている音楽は『アイドルマスター シンデレラガールズ U149』にて公開されたNightwearというシングルです。よろしくお願いします。

さて、現在私が関わっているプロダクトでは、以下のような形で、定数定義のために enumstatic letを用いたファイルが作成されています。

enum Numerics {
    static let small = 1
    static let large = 10000
}

このような定数の定義方法を見たときに、以下の疑問を抱きました。

  • static letとは何なのか
  • 名前空間を分けて定数を定義するメリットは何なのか
  • 名前空間を分けるためにenumを使うメリットは何なのか

上記の疑問点に関して、調べた結果をまとめていきます。

enumとstatic let(型プロパティ)

まず、 staticは、型自身に結びつくプロパティを定義することを可能にするSwiftの機能の1つです。 インスタンスを作成しなくても、 型名.staticプロパティ名のようにプロパティを呼び出すことができます。

enum Numerics {
    static let small = 1
    static let large = 10000
}
print(Numerics.large)
10000

型自身に結びつくため、 enumのRaw Valuesと異なる型を割り当てることが可能です。

enum Sample: String {
    case hello = "ハロー"
    case thanks = "ありがとう"
    static let small = 1
    static let large = 10000
}
print(Sample.hello.rawValue)
print(Sample.small)
ハロー
1

enumを用いた定数定義のメリット

グローバルに定数を直置きした場合、下記のような形に定数が定義されます。しかしながら以下のような問題が生じます。

  • 同一の名前が定義できない
  • 何に関連する定数なのか一目で分からない
  • 定数名が長くなってしまう
let small = 1
let large = 10000
let sampleTitle = "定数サンプル"
let sampleSubTitle = "グローバルに直置きした定数"
let sampleDescription = "このような形で呼び出せます。"

print("\(sampleTitle):\(sampleSubTitle)")
print("\(small)-\(large):\(sampleDescription)")
定数サンプル:グローバルに直置きした定数
1-10000:このような形で呼び出せます。

上記のような問題が発生した場合は enumを用いて定数定義をすることで、名前空間ごとに整理・定数名の統一を行うことができます。

名前空間とは変数や定数、関数などが所属する領域のことです。これを活用することで、同じ名前の衝突を避けつつコードの可読性を向上できます。 下記の例では Constsという大きな名前空間の中にNumericsTitleSubTitleDescriptionという名前空間を作成しています。

enum Consts {
    enum Numerics {
        static let small = 1
        static let large = 10000
    }
    enum Title {
        static let sample = "定数サンプル"
    }
    enum SubTitle {
        static let sample = "enumで管理した定数"
    }
    enum Description {
        static let sample = "定数をこのような形で定義できます。"
    }
}
print("\(Consts.Title.sample):\(Consts.SubTitle.sample)")
print("\(Consts.Numerics.small)-\(Consts.Numerics.large):\(Consts.Description.sample)")
定数サンプル:enumで管理した定数
1-10000:定数をこのような形で定義できます。

定数を Consts.Title.sampleConsts.Numerics.smallといった形で呼び出すことができます。

これにより、以下のようなメリットが得られます。

  • 定数を呼び出す際にenumの変数名(例:Consts)から自動補完ができる
  • 名前空間ごとに、定数がどのような意味・位置付けなのかを理解しやすい
  • TitleNumericsの変数名から、文字列や数字が入ることを推測しやすくなる
  • それぞれの名前空間に対して同一の定数名(sample)を定義できる

そのため、グローバルに直に置くよりも定数を整理できます。

enumを使う意味

structclassでも同様に型プロパティを使って定数管理ができます。しかし、プロパティにアクセスする以外の目的はないにもかかわらず、意味のないインスタンスを作成できてしまうという問題が発生します。

struct Numerics {
    static let small = 1
    static let large = 10000
}
var sample = Numerics() // 作成できるが使い道がない

この問題はイニシャライザの書き方を工夫することで回避できますが、単純に定数管理をしたい場合は enumを用いる方が早く解決することができます。 enumの初期化はこの形ではできず、またcaseが存在しなくても問題なく動作するため、無意味なインスタンスの作成を確実に防ぐことができます。

enum Numerics {
    static let small = 1
    static let large = 10000
}
var sample = Numerics() // エラーにより作成できない

このような性質から、どこかで定数定義をしたい場合、 structclassではなくenumを使うことが望ましいです。

おわりに

調査した結果、以下のことがわかりました。

  • static letを用いることで、型自体に結びつくプロパティを定義することができる
  • 名前空間を分けて定数を定義することで、グローバルに置くよりも整理できる
  • 名前空間を分けるため、enumを用いることで自動補完などのメリットが得られる
  • enumを使うことで、無意味なインスタンスの作成を確実に防ぐことができる

この記事で、定数定義の際に enumstatic letを用いる理由についての理解を深める一助となれば幸いです。

参考資料

アバター画像

長島大和

目次