【Kotlin超入門コース】13.クラス|クラスとは、「データ」と「処理」をまとめたもの【プログラミング初心者向け入門講座】

Kotlin超入門コース

この記事の執筆・監修

キノコード
キノコード

テクノロジーアンドデザインカンパニー株式会社のCEO。
日本最大級のプログラミング教育のYouTubeチャンネル「キノコード」や、プログラミング学習サービス「キノクエスト」を運営。
書籍「あなたの仕事が一瞬で片付くPythonによる自動化仕事術」の著者や、雑誌「日経ソフトウエア」の寄稿などの実績も多数。

はじめに

こんにちは。キノコードです。
「Kotlin超入門コース#13 クラス」について説明します。

クラスとは?

クラスにはインスタンスやコンストラクタなどの概念がでてきます。
私自身、プログラミングを勉強し始めたときに、これを理解するのに時間がかかりました。
私が何冊も書籍を読んで、こういう順番であれば理解しやすいというプロセスで説明します。
クラスを理解できた感動をみなさんにもお届けできればと思い、説明していきます。
まずクラスについて説明します。
クラスとは、「データ」と「処理」をまとめたものになります。
Kotlinでは、「データ」のことをプロパティといい、「処理」のことをメソッドといいます。

プロパティとメソッド

プロパティは、クラス内で定義された変数のことです。
プロパティは、変数と同じように、数値や文字列を代入したり、参照したりすることができます。
プロパティと変数の違いは、クラスの外にあるかクラスの中にあるかの違いです。
次にメソッドについて説明します。
前のレッスンで関数は、いろいろな「処理」をまとめて1つにしたものと説明しました。
メソッドも関数と同じで、いろいろな「処理」をまとめて1つにしたものです。
簡単にいうと、メソッドは、クラス内に定義された関数です。
まとめると、プロパティはクラス内の変数、メソッドはクラス内の関数ということになります。

クラスの定義

クラスを作ることをクラスを定義すると言います。
このレッスンでどんなクラスを定義するか説明します。
クラス名はStudentとします。
次に、数学と英語の点数の平均を計算するavgというメソッドを定義します。
コードを書いていきましょう

class Student {

    fun avg() {
        println((80 + 70) / 2)
    }

}

まずclassと書いて、次にクラス名を書きます。
今回はStudentというクラス名なので、Student。
クラス名の最初の文字は小文字でも定義はできますが、最初の文字を大文字するのは、Kotlinの慣習となっています。
クラス名の最初の文字は大文字にしましょう。
波括弧を書いて改行です。
次にメソッドを定義していきます。
数学と英語の点数の平均を計算するメソッドです。
まず、fucを書きます。
平均を計算するので、平均という意味のaverageを省略して、avgというメソッド名にします。
次に丸括弧を記述します。引数がある場合は、丸括弧内に引数を記述します。
引数は、関数と同じで引数がなくてもよいです。
また、複数の引数を定義してもよいです
今回はメソッドに渡す引数がないので、引数は記述しません。
丸括弧の次は、波括弧。改行です。
波括弧の中に、数学が80点と、英語が70点を取れたとして、それらを足して2で割ります。
表示させるためにprintlinでくくりましょう。
引数は、関数と同じで引数がなくてもよいです。
また、複数の引数を定義してもよいです
今回はメソッドに渡す引数がないので、引数は記述しません。
これで、クラスを定義することができました。

クラスの使い方

クラスを実際に使ってみたいと思いますが、クラスはこのままでは使うことができません。
クラスは、クラスから作られたインスタンスを変数に代入してから使います。
クラスは、インスタンスになって初めて使えるようになります。
コードを書いて、クラスの使い方をみていきましょう。

class Student {

    fun avg() {
        println((80 + 70) / 2)
    }

}

fun main() {
  var a001 = Student()

  a001.avg()
}

数学が80点、英語が70点という点数は、aという学級の出席番号001番の人がとったとします。
変数名をa001とします。
イコールを書いて、クラス名、丸括弧を書きます。
これで、クラスを使えるようになりました。
クラスを使えるような状態にすることを「インスタンス化」といいます。
インスタンスとは、実体という意味です。
なので、インスタンス化とは、実体化という意味です。
つまり、インスタンス化とは、クラスという型から、インスタンスという実際に使える「モノ」を作ることをいいます。
変数にインスタンスを代入して、インスタンスとして使えるようになったa001は、これからa001インスタンスと呼ぶことにします。
次にメソッドの実行方法についてです。
a001にドットをつけて、メソッド名です。
丸括弧も忘れないでください。
実行してみます。
平均点の75点が表示されました。

class Student {
  fun avg(math:Int, english:Int) {
    println((math + english) / 2)
  }
}

fun main() {
  var a001 = Student()
  a001.avg(80, 70)
}

ここまでは、80点と70点を直接、メソッド内に記述していました。
これだと生徒が変わるごとにメソッドの書き換えが必要です。
引数で渡して計算できるようにしましょう。
そうすることで、クラスの書き換えは不要になり、クラスを使い回すことができます。
クラス内に記述しているメソッドの1番目の引数をmathとします。
2番目の引数をenglishとします。
そのmathとenglishの引数を、printlinのところに記述します。
avgメソッドに80点と70点を渡して実行してみましょう。
75点となるはずです。
75が表示されました。

class Student {
  fun avg(math:Int, english:Int) {
    println((math + english) / 2)
  }
}

fun main() {
  var a001 = Student()
  a001.avg(30, 70)
}

メソッドに渡す引数を30点と70点にしてみましょう。
平均の50が表示されるはずです。
実行してみましょう。
50が表示されました。

class Student {
  var name = ""
  fun avg(math:Int, english:Int) {
    println((math + english) / 2)
  }
}

fun main() {
  var a001 = Student()
  a001.avg(80, 70)
  a001.name = "sato"
  println(a001.name)
}

次にプロパティについてみていきましょう。
プロパティは、クラス内に定義された変数のことです。
プロパティを定義していきます。
佐藤さん、鈴木さんといったような名前を代入したいので、プロパティ名をnameにします。
nameは、ダブルクオテーション2つで、空の値を代入させておきます。
次に、インスタンスのプロパティに値を代入します。
a001、ドット、プロパティ名を書いて、値を代入します。
値はsatoさんとしましょう。
これでプロパティの定義はおわりです。
printlinで表示させてみましょう。
実行してみましょう。
メソッドの結果の75とプロパティのsatoが表示されました。

class Student {
  var name = ""
  fun avg(math:Int, english:Int) {
    println((math + english) / 2)
  }
}

fun main() {
  var a001 = Student()
  a001.avg(80, 70)
  a001.name = "sato"
  println(a001.name)
  println(a001.gender)
}

仮に、性別という意味のgenderというまだ定義していないプロパティを表示させてみましょう。
定義していないのでエラーと表示されます。
実行してみましょう。
エラーが表示されました。
このように未定義のプロパティはエラーが表示されます。

class Student {
  var name = ""
  fun avg(math:Int, english:Int) {
    println((math + english) / 2)
  }
}

fun main() {
  var a001 = Student()
  a001.avg(80, 70)
  a001.name = "sato"
  println(a001.name)

  var a002 = Student()
  println(a002.name)
}

また、a002というインスタンス名でインスタンス化をしたあとに、
nameのプロパティを表示させてみましょう。
実行してみましょう。
何も表示されませんでした。
このようにプロパティは、インスタンスごとに存在します。
逆の言い方をすれば、インスタンスごとに、プロパティを定義しなければなりません。
つまり、インスタンスごとにプロパティが存在するので、新しいインスタンスを作るごとに、プロパティを定義する必要があります。
そのため、10個インスタンスを作ったとすると、インスタンスごとにプロパティを10個定義する記述をしなければなりません。
先ほどの例でいうと、「 a001.name」のような記述をインスタンスごとに10個、記述しなければなりません。
その不便さを解消するものがコンストラクタです。
Kotlinでは、プライマリコンストラクタと呼ばれています。
コンストラクタの書き方について説明します。
クラス名のあとに、constructor、丸括弧。丸括弧内に引数を書きます。その次に、波括弧を書きます。
丸括弧の中に引数を書きます。
constructorのキーワードは、基本的には省略することができます。
一部の条件を満たすときは、constructorをつける必要があります。
ここは、説明が長くなるので、超入門コースでは省きます。
インスタンス化をするときに、引数の値をプロパティにセットすることができます。
そのため、あとから使うプロパティは、コンストラクタで自動的に作っておけばよいのです。
なお、引数の前に、valやvarをつけることで、プロパティを省略することができます。

class Student constructor(name: String) {
  var name = name
  fun avg(math: Int, english: Int) {
    println((math + english) / 2)
  }
}

fun main() {
  var a001 = Student("sato")
  println(a001.name)

  var a002 = Student("tanaka")
  println(a002.name)
}

コンストラクタの記述方法をみていきましょう。
まず、クラス名のあとに、constructorを書きます。
次に、丸括弧。丸括弧の中に引数を書きます。
引数は、佐藤さん、田中さんといったような名前を代入したいので、nameにします。
プロパティに引数を渡したいので、nameを代入します。
これでコンストラクタの記述は終わりです。
次に、Studentの丸括弧内に、プロパティにセットしたい値を書きます。
ここでは、a001にはsato、a002にはtanakaを書きます。
sato、tanakaが表示されるはずです。
実行してみましょう。
sato、tanakaが表示されました。

class Student (var name: String) {
  fun avg(math: Int, english: Int) {
    println((math + english) / 2)
  }
}

fun main() {
  var a001 = Student("sato")
  println(a001.name)

  var a002 = Student("tanaka")
  println(a002.name)
}

次に、constructorを省略してみます。
また、引数の前にvalやvarをつけて、プロパティを省略してみます。
実行してみましょう。
sato、tanakaが表示されました。
以上がコンストラクタの使い方です。
このクラスの便利なところはどんなところでしょうか?
クラスは一度、定義しておけば、あとからいくらでもインスタンスを作ることができます。
車を作る「設計図」がクラス、たい焼きを作る「金型」がクラスと表現したりもします。
もう1つ表現するなら、クラスは、パソコンで使うコピペです。
コピペでどんどんインスタンスを作ることができます。
もしクラスがなければ、生徒ひとりひとりのためにStudentクラスを書かなければいけないので面倒です。
しかしクラスがあるから、コピペのように各生徒のインスタンスを作ることができます。
クラスがあるから効率よくプログラミングすることができます。