Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

Swift
入門編

  1. Swiftとは
  2. Swift実行環境の構築について
  3. print()を使って出力してみよう
  4. コメントとコメントアウトについて
  5. 文字列とエスケープシーケンスについて
  6. 数値について
  7. 基本的な演算子の使い方とオペランドについて
  8. 真偽値と比較演算子について
  9. データ型とは
  10. 変数と定数について
  11. 変数と定数の使い方
  12. 配列とは
  13. 配列の要素の追加や削除について
  14. 配列の使い方
  15. 辞書(Dictionary)とは
  16. 辞書のプロパティの追加や削除について
  1. nilとオプショナルについて
  2. 関数とは
  3. 引数と仮引数について
  4. 内部引数名と外部引数名について
  5. 返り値(戻り値)とreturnについて
  6. タプル(tuple)について
  7. 関数のオーバーロードについて
  8. もし〜ならばというif文について
  9. 論理演算子について
  10. 処理を分岐させるswitch文について
  11. 繰り返しのfor-in文と範囲演算子について
  12. ループ処理のwhile文とrepeat-while文について
  13. 処理を抜けるbreak文とcontinue文について
  14. クラスとインスタンスについて
  15. イニシャライザ(コンストラクタ)について
  16. 関数とクラスの使い分けについて
  1. トップページ
  2. Swift入門編 - クラスとインスタンスについて

クラスとインスタンスについて

みなさまどうも。

今回のこの記事でSwift入門編30話目でございます。ここまでお読み頂いた方は大変お疲れ様でございます。そして初めていらっしゃった方はどうぞごゆるりとされてしまって下さい。

さて、今回は超重要項目である『クラス』(class)と『インスタンス』についてやっていきます。

『クラス』と『インスタンス』の使い方とか概念とかは先の記事で解説しますので最初に文法とかから確認していきます。というわけでサンプルをどん。

class Test {

}

クラス『Test』を定義してみました。『クラス』を定義するには上記のように『class』と書いて、その後に半角スペースとかをあけて、任意の識別子(名前)を書いてあげます。そしたら『{}』を書いて、その中に処理を書いていく感じになりますね。

日本語で書くとこんな感じです。

class クラス名 {
    // ここに処理....
}

『クラス』の定義についてはこれだけですね。ここまでは問題ないかと思います。

ちょっとネーミングに関しての注意点ですが、『クラス』の識別子(名前)は最初の一文字を大文字にするアッパーキャメルケースにした方が無難です。

例えば『test of class』という意味にしたい場合は『TestOfClass』って感じの記述になりますね。

他の言語や現場のコーディングルールによって違ってしまう場合がありますが、Swiftでのクラス名として使用する識別子はアッパーキャメルケースで記述するのがお作法になってます。

さて、さきほどのサンプルだと中身が空で全く意味がないのでちょいと中に処理を書いてみましょう。とりあえず定数『n』を書いてみます。

class Test {
    let n = 1
}

さらにもういっちょ変数とか関数も記述してみます。

class Test {
    let n = 1
    var _n = 2

    func f(){
        print(n)
        print(_n)
    }
}

これで中身のある『クラス』が出来ました。

さて、この『クラス』の中に書いてある処理を実行してみたいと思いますが、ここで気をつけなくてはならないことがあります。

『クラス』は簡単に例えると「定数や変数、関数などの処理をまとめた設計図」のようなものになるのでございます。

ちょいと関数を思い出してみましょう。関数の場合は「関数を定義したら任意のところで実行させるだけ」というシンプルな流れでしたよね。

func test() { // 関数を定義します。
    print("初音ミク")
}

test() // 実行します。

しかし、『クラス』の場合はあくまでも設計図みたいな存在なので、『クラス』を定義した時点では実体がないんですよね。

なので中に書いてある処理を実行するためには、その設計図を元した実体を生成しないといけません。これが『インスタンス』と呼ばれるものになります。『インスタンス』を生成するにはこんな感じで記述します。

class Test {
    let n = 1
    var _n = 2

    func f(){
        print(n)
        print(_n)
    }
}

Test() // クラス『Test』を元にした実体を作ります。これが『インスタンス』です。

上記の『Test()』というところに注目してみましょう。『Test()』というように『クラス名()』とすることで『インスタンス』が生成できます。関数を実行させるときと同じような感じですね。

そしたらその生成した『インスタンス』の中身にアクセスしてみましょう。以下はクラス『Test』の中にある定数『n』を出力している感じですね。

class Test {
    let n = 1
    var _n = 2

    func f(){
        print(n)
        print(_n)
    }
}

print(Test().n) // クラス『Test』を元に生成した『インスタンス』の中にある定数『n』の中身の『1』を出力します。

上記の『Test().n』というところに注目です。このように『.』を使って『インスタンス.識別子』とすることでそのデータにアクセスすることができます。

そんでもって、クラス『Test』の中にある関数『f』を実行させるとなるとなるとこうなります。

class Test {
    let n = 1
    var _n = 2

    func f(){
        print(n)
        print(_n)
    }
}

Test().f() // クラス『Test』を元に生成した『インスタンス』の中にある関数『f』を実行します。

『Test().f()』といったように『インスタンス.関数名()』という感じで記述すればOKです。関数実行のトリガーである『()』を付けているのがミソですね。

というわけで『クラス』を元にした『インスタンス』を作ってその中の処理にアクセスしたり実行したりするということはできました。

ここでちょっと覚えておいてほしい項目があり、『クラス』という概念の特性上、上記の『Test().n』や『Test().f()』といったように「『インスタンス』を作ってそのままその『インスタンス』に対して何かを行う」ということはあまり行われません。

「作った『インスタンス』は変数や定数に入れてから使う」というのが一般的です。以下のような感じですね。

class Test {
    let n = 1
    var _n = 2

    func f(){
        print(n)
        print(_n)
    }
}

let testA = Test() // 一度定数に『インスタンス』を代入してあげます。

print(testA.n) // 定数『testA』を使って処理をします。
testA.f() // 定数『testA』を使って処理をします。

状況によっては「『インスタンス』を作って即何かをする」というのも効果的だったりするので必ず守らなくてはいけない、というわけではありませんが、基本的には上記の変数や定数に代入してから使うようにするのが一般的な手法になります。

ここまでは大丈夫そうでしょうか。ちょっとややこしい感じだと思うので関数を使う場合と『クラス』を使う場合の処理の流れをまとめておきます。

関数の場合はこうなります。

  1. 関数を定義する。
  2. その関数を実行する。

『クラス』の場合はこうです。

  1. 『クラス』を定義する。
  2. その『クラス』を元に『インスタンス』を作る。
  3. 『インスタンス』を使って処理を行う。

関数と比べてみると大分複雑になっていますね。

処理を行うときは定義した『クラス』ではなく『インスタンス』を使う必要がある、というのも引っかかりやすいポイントになってますのでご注意です。

あと各種の呼び名についても確認しておきましょう。

『クラス』の中に記述した変数とか定数とか関数とかをまとめて『プロパティ』と呼びます。そんでもって『クラス』の中に記述された関数は『メソッド』と呼びます。

そしてちょっとややこしいのですが、『プロパティ』とか『メソッド』とかいう呼び名は言語によって違ったり、人によって違ったりしてしまう場合があります。

例えば、javaScriptの場合はオブジェクトの中に入ってる関数が『メソッド』と呼ばれ、Javaの場合は『クラス』の中で定義した変数は『メンバ変数』と呼ばれます。

まあ、指してるものは大体同じようなものなので関数のことを『メソッド』と呼んでしまったり、『クラス』の中で定義した変数を単純に変数と呼んでしまったりしても全然OKな気がします。OKじゃなかったらごめんなさい。

ちなみに当サイトでは『プロパティ』とかの単語を使うと分かりづらくなってしまう場合もあるというコンセプトの元、「『クラス』の中の変数」って感じで解説していくつもりです。その辺はご了承下さい。

あと最後に『インスタンス』の『プロパティ』を上書きできる、ということも確認しておきましょう。以下のサンプルを見て下さい。

class Test {
    let n = 1
    var _n = 2

    func f(){
        print(n)
        print(_n)
    }
}

let testA = Test() // 『インスタンス』を作ります。

クラス『Test』の中には定数『n』と変数『_n』がいますね。その『プロパティ』の変数とかは上書きOKだったりします。定数はダメです。こんな感じですね。

class Test {
    let n = 1
    var _n = 2

    func f(){
        print(n)
        print(_n)
    }
}

let testA = Test() // 『インスタンス』を作って定数『testA』に代入します。

testA._n = 10 // 『インスタンス』の中の変数『_n』を上書きします。

testA.f() // 『1』と『10』が出力されます。

testA.n = 10 // 定数は上書きできません。エラーです。

クラス本体じゃなくて変更するのは『インスタンス』になります。ここ間違いやすいところなので気をつけて下さい。

そしてもういっちょ注意点です。『インスタンス』が代入されている『testA』に注目して下さい。これ、『let』で宣言されていますね。なので『プロパティ』を変更できないかと思いきや『プロパティ』は変更OKだったりします。

ちょっとややこしいのですが、「『let』の場合は『インスタンス』の再代入ができなくなる」という動作になります。こんな感じですね。

class Test {
    let n = 1
    var _n = 2

    func f(){
        print(n)
        print(_n)
    }
}

var testA = Test() // 『var』で宣言した『testA』に『インスタンス』を代入します。

testA._n = 10 // 『インスタンス』の中の変数『_n』を上書きします。

testA.f() // 『1』と『10』が出力されます。

testA = Test() // 『testA』に再度『インスタンス』を代入します。『var』で宣言されているためOKです。

testA.f() // 再度『インスタンス』が作られたので『1』と『2』が出力されます。

let testB = Test() // 『let』で宣言した『testB』に『インスタンス』を代入します。

testB = Test() // 『let』で宣言されているため再代入はできません。

かなりややこしいのですが、間違えないように気をつけて下さい。

というわけでとりあえずの『クラス』と『インスタンス』についてはこんな感じになります。

次の記事では『イニシャライザ』についてやっていきましょう。『クラス』の使い方とか概念とかの解説はその後にしますので今は気にせず先に進んでしまって下さい。

ではではこの辺で。またお会いしましょう。

この記事は桜舞が執筆致しました。

著者が愛する小型哺乳類

桜舞 春人 Sakurama Haruto

ISDN時代から様々なコンテンツを制作しているちょっと髪の毛が心配な東京在住のプログラマー。生粋のロングスリーパーで、10時間以上睡眠を取らないと基本的に体調が悪い。好きなだけ寝れる生活を送るのが夢。ゲームとスポーツと音楽が大好き。誰か髪の毛を分けて下さい。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。