
こんにちは!リンコですピヨ!この記事では自分の勉強の復習もかねて、Kotlinでのオーバーロードとポリモーフィズムを記述する方法を解説するピヨ!
この第22章では、プログラミング言語であるKotlinのオーバーロードとポリモーフィズムについて、一緒に勉強していきましょう。
この記事を読めばプログラミング未経験の方も、Kotlin入門レベルのオーバーロードとポリモーフィズムについて1つ1つ理解しながら勉強できると思うので、是非最後まで読んで頂ければと思います。
※この記事で出てくる「サンプルコード」は、記述が長く画面からはみ出ている場合がありますが、横にスライドすると表示されるのでご安心ください。
【Kotlin】オーバーロードとは?
ではまず、オーバーロードというのはどんな処理のことを言うのでしょうか?オーバーロードについて勉強していきましょう。
オーバーロードは多重定義のこと
オーバーロード(overload)は、関数の多重定義のことになります。
関数名は完全に一致しているが、関数が受け取るパラメータを異なるものにすることによって、別のバージョンの関数を作ることを言います。
オーバーライドと言葉が似ているので注意
前章で勉強したオーバーライド(override)とは、名前が似ていますが別物になるので注意しましょう。
オーバーライドは、関数名とパラメータが完全に一致するように継承元の関数を継承先で上書きすることを言います。

オーバーロードは関数が受け取るパラメータを違うものにすることで別の関数を作ることピヨ!
【Kotlin】オーバーロードの実装前と実装後のコードを見比べてみよう
オーバーロードがどのようなものかざっくりわかったところで、オーバーロードを実装したコードを見て勉強していきましょう。
オーバーロードを実装することで、実装前とどう違うのか見るために、2つのコードを見比べながら勉強していきます。
オーバーロードを実装していないコード
ではまず、オーバーロードを実装していないコードから見ていきましょう。
コード
fun main() { val bird1 = Rinko("黄色") val bird2 = Sparrow("グレー") flyByRinko(bird1) flyBySparrow(bird2) } fun flyByRinko(bird: Rinko) { bird.fly(10.0) } fun flyBySparrow(bird: Sparrow) { bird.fly(10.0) } open class Bird(val color: String) { var distance = 0.0 open fun fly(d: Double) { distance = distance + d println("${color}の鳥が${d}km飛びました。") println("その結果、飛行距離は${distance}kmになりました。") } } class Rinko(color: String) : Bird(color) { override fun fly(d: Double) { distance = distance + d println("${color}のリンコが飛んでいます!ピヨピヨ!") println("飛行距離は${distance}kmになったピヨ!") } } class Sparrow(color: String) : Bird(color) { override fun fly(d: Double) { distance = distance + d println("${color}のスズメが飛んでいます!チュンチュン!") println("飛行距離は${distance}kmになったチュン!") } }
出力
黄色のリンコが飛んでいます!ピヨピヨ! 飛行距離は10.0kmになったピヨ! グレーのスズメが飛んでいます!チュンチュン! 飛行距離は10.0kmになったチュン!
上記では、リンコとスズメに10km飛んでもらっています。
文法的に間違っていないので問題なく動作し出力されていますが、Kotlinらしくないコードになっています。
いったいどこが悪いのかと言うと「flyByRinko」と「flyBySparrow」と2つの関数の定義がほぼ同じ内容であるというところです。
ほぼ同じ名前で同じコードが記述されてしまっているので、まずここの関数名を揃えてKotlinらしいスッキリしたコードにしたいですね。

Kotlinのコードならもっとスッキリできるピヨ!
オーバーロードを実装しているコード
では続いて、オーバーロードを実装しているコードを見ていきます。
コード
fun main() { val bird1 = Rinko("黄色") val bird2 = Sparrow("グレー") flyByBird(bird1) // 「flyByRinko」を「flyByBird」に変更 flyByBird(bird2) // 「flyBySparrow」を「flyByBird」に変更 } // 「flyByRinko」を「flyByBird」に変更 fun flyByBird(bird: Rinko) { bird.fly(10.0) } // 「flyBySparrow」を「flyByBird」に変更 fun flyByBird(bird: Sparrow) { bird.fly(10.0) } // 上記以降は同じなので割愛します
出力
上記と同じ
このコードでは「flyByRinko」と「flyBySparrow」を両方とも「flyByBird」に統一しました。つまり「flyByBird」という全く同じ名前の関数が、2つ存在している状態にしたことになります。
この2つの関数の違う点は、パラメータの型が1つは「Rinko型」で、もう1つは「Sparrow型」の変数を受け取っているという点です。このように関数名が同じでも「パラメータの型が違う」と、それぞれ独立した別々の関数として扱われるようになります。
また呼び出し側の記述だけを見ると同じ関数を呼んでいるように見えますが「flyByBird(bird1)」は「bird1」がRinko型なので、Rinko型をパラメータとして受け取る方の関数の呼び出しになっています。
「flyByBird(bird2)」は「bird2」がSparrow型なので、Sparrow型をパラメータとして受け取る方の関数の呼び出しになっています。
このように同じ名前でパラメータの型やパラメータの数が違う関数を作ることを「関数のオーバーロード」と言います。

オーバーロードはよく使うのでしっかり覚えるピヨ!
【Kotlin】ポリモーフィズムとは?
オーバーロードについて勉強したところで、続いてポリモーフィズムについて勉強していきます。まずはポリモーフィズムがどんな内容なのかを勉強していきましょう。
日本語で「多様性」という
ポリモーフィズムは、日本語で言うと「多様性」という言葉になります。
この多様性(ポリモーフィズム)とは「抽象クラス」や「インターフェース」を活用して関数の呼び出しを共通化し、さらに「オーバーロード」させることで、同じ関数を呼び出してもインスタンス毎に違う動きにさせることです。
スッキリしたコードにすることができる
ポリモーフィズムを使うことによって、関数の呼び出し方が共通化できるためコードも短縮でき、Kotlinのコードはかなりスッキリしたコードにすることができます。

ポリモーフィズムは類似の関数の呼び出しを共通にすることピヨ!
【Kotlin】ポリモーフィズムの実装前と実装後のコードを見比べてみよう
ポリモーフィズムがどのようなものかわかったところで、ポリモーフィズムを実装したコードを見て勉強していきましょう。
オーバーロードと同様、ポリモーフィズムを実装することで実装前とどう違うのか見るために、2つのコードを見比べながら勉強していきましょう。
ポリモーフィズムを実装していないコード
ポリモーフィズムを実装していないコードから見ていきます。以下のコードは、先程のオーバーロード実装後と同じコードになります。
コード
fun main() { val bird1 = Rinko("黄色") val bird2 = Sparrow("グレー") flyByBird(bird1) flyByBird(bird2) } fun flyByBird(bird: Rinko) { bird.fly(10.0) } fun flyByBird(bird: Sparrow) { bird.fly(10.0) } // 上記以降は同じなので割愛します
出力
黄色のリンコが飛んでいます!ピヨピヨ! 飛行距離は10.0kmになったピヨ! グレーのスズメが飛んでいます!チュンチュン! 飛行距離は10.0kmになったチュン!
オーバーロードを実装したコードですが、まだ少し長ったらしく感じますよね。なぜ長ったらしく感じるかというと、2つの「flyByBird」関数の中身がほぼ一緒だからです。
これを何とかするために活用できるのが「ポリモーフィズム」の考え方になります。これにはRinkoクラスとSparrowクラスの両方の基底クラスがBirdクラスであることを利用します。
ポリモーフィズムを実装しているコード
ではポリモーフィズムを実装しているコードを見ていきましょう。
コード
fun main() { val bird1 = Rinko("黄色") val bird2 = Sparrow("グレー") flyByBird(bird1) flyByBird(bird2) } fun flyByBird(bird: Bird) { bird.fly(10.0) } // 上記以降は同じなので割愛します
出力
上記と同じ
見比べてみると「flyByBird」という関数が2つから1つになっていて、flyByBirdが受け取るパラメータの型が「Bird」になっていることがわかります。
これはRinkoクラスとSparrowクラスの「継承元(基底クラス)」が共通の「Birdクラス」だからできることになります。
この「flyByBird」を呼び出すと、1回目は「bird1」がパラメータとして引き渡されるので、Rinko型ということになり、黄色のリンコが動きます。
2回目は「bird2」がパラメータとして引き渡されるので、Sparrow型ということになり、グレーのスズメが動きます。
このようにRinkoもSparrowもBirdという基底クラスを継承したクラスなので、まとめて処理したい時はBirdとして処理することができます。
この機能を利用すれば、様々なタイプのインスタンスを受け取る関数の定義を1つ記述するだけでOKになります。これがポリモーフィズム(多様性)です。

ポリモーフィズムの概念は少し難しく感じるけど、覚えると意外と簡単だからしっかり復習するピヨ!
まとめ
この記事では、プログラミング言語であるKotlinのオーバーロードとポリモーフィズムについて勉強していきましたが、いかがでしたでしょうか?今回の記事をまとめると以下のようになります。
- オーバーロードは関数が受け取るパラメータを違うものにすることで別の関数を作ること
- ポリモーフィズムは類似の関数の呼び出しを共通にすること
- オーバーロードとポリモーフィズムを使うことで、複数インスタンスを受け取る関数定義が1つだけでよくなりコードがスッキリする
今回勉強した「オーバーロード」や「ポリモーフィズム」はKotlinの入門レベルの知識になるので、何回も読み直してしっかり覚えておきましょう。

次回の記事では「抽象クラスとインターフェース」について勉強していくピヨ!
プログラミング未経験の方や入門レベルの方、Kotlinについて詳しくなりたい方は、また一緒に勉強するピヨ!
コメント