C++/C#/Java オーバーロードを使うべき3つのポイント | 株式会社リッカWebサイト

株式会社リッカ

BLOG
ブログ詳細

2016-04-01C++/C#/Java オーバーロードを使うべき3つのポイント

overload_2-1

はじめに

今回は、オーバーロードを使ったワンランク上の設計・実装方法を説明します。
使いどころとして3つのポイントがあり、
・コードの視認性向上
・クラスの再利用性
・既存コードへの影響低減
を意識する時に使います。
今回もC#で書きますが、C++, Javaなどオブジェクト指向言語でも同じです。

やさしさのためのオーバーロード

オーバーロードはライブラリや共通クラス、ユーティリティーを作る人が気を利かせて実装するものだと考えています。

例えば.NETのクラスライブラリにあるSystem.IO.StreamReaderはファイルを読み込むときに使います。
こいつのコンストラクタは11個用意されていて、
ファイルパスとStreamの両方からインスタンスを生成することができ、
エンコード、BOMの有無、バッファーサイズ、ストリームを開いたままにするかの指定はオプションとなっています。
詳しくはこの辺で
https://msdn.microsoft.com/ja-jp/library/system.io.streamreader(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1

つまり.NETのクラスライブラリの様に不特定多数の人が利用するようなクラスは、
オーバーロードを定義して使う人への配慮を行います。
小規模でも複数の人がかかわるプロジェクトでは共通クラスを作る際も、
オーバーロードを定義すると、「これを作ったやつはやさしいなー」と思われると思います。

やさしくないUtilityの例

データーベース(配列)から成績を取ってきて、
ファイルに書き込むプログラムの例を書いてみました。
これは優しくない方です。

わざわざ、ループさせて、ToString()で文字の変換までさせていますね…

やさしいUtilityの例

やさしくないUtilityをやさしく書き換えてみました。

なんと利用者のコードは1行…しかもシンプル…
だけど、FileUtilityの中は泥臭いですね。
しかし、変換処理をFileUtilityで吸収し利用者への配慮が感じられます。

ポイント

  1. オーバーロードで必要な機能(今回はファイルの出力)は極力一か所で行う。
    ->void Write(string score)
  2. 1以外のオーバーロードはデータの変換に徹する。
  3. 2は最終的に1を利用する。
    int -> int[] -> string[] -> string -> ファイルへ

こうすることで、複雑なファイル処理をあちこちにばらまくこともなくなります。
単体試験も普通に一個ずつオーバーロードを書いて行くよりかは楽になるはずです。

まとめ

上のコードは

  • コードの視認性向上
  • クラスの再利用性

が上がっています。
利用者側のコードがすっきりしたし、
FileUtilityクラスはテスト結果以外も出力できそうですから、
クラスの再利用性も確認できました。

力強いオーバーロード

オーバーロードの使いどころはもう一個あって、
すでにある機能と似たような処理が必要になった時、
既存コードを利用して影響を極力与えず実装することができます。
これはたぶん小技みたいなものだと思いますが、強力です。

例えば

データベース(配列)から取得した文字列を整数に変換し、
0から100の範囲だったとき整数を表示、範囲外なら表示しない。
と言うようなことを行うプログラムがあったとします。

Show(string str)の様に既存のコードに、”すでにある機能と似たような処理”として、
データが0から100であるかを事前にチェックしたい。
範囲外の値があったら、エラーを出力してデータの出力はしなくてよい。
と言う追加の要望があった場合、

と言う感じでコピペしてメソッドを追加しますか?
オーバーロードを使うとスマートに実装できます。

overload_2-2

ポイント

  1. 既存のメソッドに引数を追加する。チェックだけならtrue, 表示もするならfalse。
  2. 既存のメソッドと同じ引数のオーバーロードを作成する
  3. Check用のメソッドを作成する
  4. 2,3は1を呼び、true, falseを変更する

既存のShowメソッドはほとんど変更せずに済みました。
単体試験も簡単に通せるでしょう。
また、仕様変更でint から doubleにして!
と言われても1メソッド修正すれば済みます。

まとめ

C++とC#にはデフォルト引数が使える場合があるので、
デフォルト引数で代用すれば、わざわざShow(string str)とCheck(string str)を作らなくてもいいです。
しかし、メソッド名で機能を推測できるようにするためには、Checkを用意した方がいいと思います。

オーバーロードの力強さを感じていただけましたか?

overload_2-3

総まとめ

今回は、新人の子に「オーバーロードはなんのためにあるか考えてみて」と課題を出しましたが、
色々探したけど、使いどころみたいのってあまり説明されてないんですよね…
なのでちゃんと自分も答えを示せるようにブログにまとめました。

オーバーロードは使い方を間違えると意味の分からないコードを生み出しますが、
使い方によっては、ワンランク上の設計・実装ができるようになります。
いいポイントを見つけて実装してみましょう!!