前回、「クラスの基本構造(変数、関数、継承)」でクラスの作成や継承について紹介しました。

その中で、メソッド(関数)のオーバーライドを使いましたが、今回はオーバーロードについて触れておきたいと思います。
引数違いの同一関数名
引数の数が異なる同一関数名はよく使われていると思いますが、引数の数は同じだけど受け取る引数の型が違う関数をオーバーロードと呼びます。
Kotlin や Java の場合は型を明確に宣言するので可能なんだなってイメージできますが、PHP ではオーバーロードはサポートされていません。
早速、サンプルを書いてみます。前回のリラックマプログラムを少し調整してみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
fun main(args: Array<String>) { val rira = Rilakkuma("リラックマ") profileForChar(rira) val korira = Korilakkuma("コリラックマ") profileForChar(korira) } fun profileForChar(kuma: Rilakkuma) { kuma.profile() kuma.wear() } fun profileForChar(kuma: Korilakkuma) { kuma.profile() kuma.wear() } open class Character(val name: String) { fun profile() { println("名前は%sです。".format(name)) } open fun wear() { } } class Rilakkuma(name: String) : Character(name) { override fun wear() { println("茶色い着ぐるみを着ています。お腹は白いですよ。\n") } } class Korilakkuma(name: String) : Character(name) { override fun wear() { println("白い着ぐるみ?を着ています。赤いボタンがトレードマークですよ。\n") } } |
Character クラスを継承した、Rilakkuma クラスと Korilakkuma を作成して wear() メソッドをオーバーライドしています。
main 関数でそれぞれのクラスのインスタンスを生成し、profileForChar() 関数を実行します。
この時 profileForChar() の引数は、Rilakkuma クラスと Korilakkuma クラスのインスタンスを受け付けるように 2 つ用意されています。
これがオーバーライドになります。
ポリモーフィズムを使って簡潔にする
上記サンプルで引数違いの同一関数を実行しましたが、profileForChar() の中で同じ処理を書いているのでちょっとしっくりきません。
それぞれの引数のクラスによって振る舞いがバラバラであればこれでもいいのですけどね。
せっかく同じ Character クラスを継承しているクラスを引数として処理させているので、これを 1 つの関数にまとめてしまいます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
fun main(args: Array<String>) { val rira = Rirakkuma("リラックマ") profileForChar(rira) val korira = Korirakkuma("コリラックマ") profileForChar(korira) } fun profileForChar(kuma: Character) { kuma.profile() kuma.wear() } open class Character(val name: String) { fun profile() { println("名前は%sです。".format(name)) } open fun wear() { } } class Rirakkuma(name: String) : Character(name) { override fun wear() { println("茶色い着ぐるみを着ています。お腹は白いですよ。\n") } } class Korirakkuma(name: String) : Character(name) { override fun wear() { println("白い着ぐるみ?を着ています。赤いボタンがトレードマークですよ。\n") } } |
profileForChar() が 1 つになり、引数の型は Character となりました。
この Character は Rirakkuma や Korirakkuma の継承元の基底クラスですが、この基底クラスに profile() と wear() のメソッドが定義されているので、引数の Character クラスのインスタンスがリラックマかコリラックマかを意識しなくてもいいのです。
継承させるようなクラス構造を定義していなければ意識することはないですが、今回のように似たようなオブジェクトを定義する際は活用できるパターンとなります。
次回はインタフェースについても触れたいと思います。私が一番扱いに困った機能です。