4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

initとstatic funcの使い分け(Swift)

Last updated at Posted at 2025-01-09

はじめに

ふと「イニシャライザ(コンストラクタ)と Self を返すstatic funcの使い分けって何だろう?」と思ったので、自分の言葉でまとめてみます。

あくまで自分の考えなので、参考程度に留めてもらえればと思います。

環境

  • OS: macOS Sonoma 14.5
  • Xcode: 16.2 (16C5032a)
  • Swift: 6.0.3

注意

あくまで「 Self を返すstatic func」とイニシャライザの比較なので、BuilderパターンやFactory Methodパターンなどの複雑なパターンについては本記事では考慮しません。

結論

まず結論を述べます。
static funcはstatic letやstatic varも含めます。

  • インスタンスに名前を付けられる → static func
  • インスタンスに名前を付けられない → init

たったこれだけです。

インスタンスに名前を付けられる

インスタンスに名前を付けられる場合はstatic funcを使います。
この説明だけではピンと来ないかもしれないので、具体例を挙げます。

例1: 特別な値を返す

特別な値を返す場合、意味がわかるように名前を付けます。

例えばSwiftUIの Color で赤を返す場合は red 、青を返す場合は blue と名付けられるのでstatic funcとします。

定義
public struct Color {
    public static let red: Self = ...
    public static let blue: Self = ...
}
呼び出し
Text("Foo")
    .foregroundStyle(.red)

initでも実現できますが、冗長になります。

❌定義(冗長)
public struct Color {
    public enum Type {
        case red
        case blue
    }

    public init(type: Self.Type) {
        switch type {
        case .red: ...
        case .blue: ...
        }
    }
}
❌呼び出し(冗長)
Text("Foo")
    .foregroundStyle(.init(type: .red))

例2: Singletonパターン

よく使われるパターンとして、Singletonパターンを紹介します。
sharedcurrent などと名付けることが多いです。

Singletonを実現するため、initはprivateにします。

定義
public final class FooDataSource {
    public static let shared: FooDataSource = .init()

    private init() {}

    public func foo() {
        ...
    }
}
呼び出し
FooDataSource.shared.foo()

これでSingletonのインスタンスを呼び出しているとわかりやすくなります。

インスタンスに名前を付けられない

インスタンスに名前を付けられない場合はinitを使います。

例1: カラーコードから色を生成する

例えば16進数のカラーコードから Color を生成する場合、カラーコードによって赤にも青にもなり得るため、名付けられません。

定義
public struct Color {
    public init(hex: String) {
        ...
    }
}
呼び出し
let red: Color = .init(hex: "#FF0000")

例2: 引数を保持するだけ

渡された引数をそのまま保持したり、少しだけ加工したりする場合も、名付けられないのでinitを使います。

定義
public struct Foo {
    public let title: String
    public let description: String
    public let url: URL?

    public init(
        title: String,
        description: String,
        urlString: String
    ) {
        self.title = title
        self.description = description
        self.url = URL(string: urlString)
    }
}
呼び出し
let foo: Foo = .init(
    title: "Foo",
    description: "Bar",
    urlString: "https://example.com"
)

よく見るinitだと思います。

おわりに

自分なりにinitとstatic funcの使い分けを考えてみましたが、どうでしょうか。
名付けられなくても加工する処理が重い場合はinitでなくstatic funcを使うなど、他の観点もあると思います。

ぜひ本記事と異なる観点があればコメントなどで教えてもらえると嬉しいです :relaxed:

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?