Product クラスで税込価格
550 という数字が、4 画面に散らばる
送料の判定を、こんな形で書き始めたとします。
Java
int shipping = subtotal >= 3000 ? 0 : 550;これ自体は動きます。問題は 550 と 3000 です。同じ判定が商品一覧、カート、注文確認、領収書と 4 か所に散らばったあとで送料が変わったら、550 を検索して直して回り、1 か所見落として、領収書だけ金額が合わない朝が来ます。
読む側にも不親切です。その 550 が送料なのか手数料なのか、コードからは判断できません。意味のある数字が名前を持たないままコードに書かれている状態を マジックナンバー と呼びます。これから扱う税率も、まったく同じ立場の数字です。
数字に名前を付けて 1 か所に置く
Java では、変わらない値をこう書きます。
Java
private static final double TAX_RATE = 0.10;finalは「一度決めたら変えない」。あとから代入しようとするとコンパイルエラーになりますstaticは「インスタンスごとではなくクラスに 1 つ」。商品が 1000 個あっても税率は 1 つで足ります- 名前は大文字とアンダースコアでつなぐのが Java の慣習です
こうしておけば、税率が変わる日に直すのは 1 行だけです。計算式のほうにも TAX_RATE という名前が現れるので、何を掛けているのかが読んだ瞬間に伝わる、という副産物も付いてきます。
int だけで書くと、静かに壊れる
税率を int のまま書こうとすると、エラーも出さずに壊れます。
Java
double rate = 10 / 100; // 0.1 ではなく 0.010 / 100 は int 同士の割り算なので、答えは小数ではなく 0 へ切り捨てられ、そのあと double に入ります。片方を 100.0 と書けば 0.1 になります。定数を最初から double で持っておけば、この罠は踏みません。
逆に、double の計算結果を円の整数に戻すときは (int) でキャストします。キャストは四捨五入ではなく 切り捨て です。
Java
System.out.println((int) 108.9); // 108やってみよう
右のエディタで productTotal(int price) を完成させます。税抜価格を受け取り、税込価格を int で返します。
ただし、計算を productTotal の中に直接書かないでください。Product というクラスを作り、税抜価格をフィールドに持たせ、税込価格を返すメソッドをその中に置きます。税率は上で見た static final の定数にします。productTotal の仕事は、new で商品を 1 つ作って、そのメソッドの結果を返すだけです。
緑になったら、定数を 0.08 に書き換えてみてください。productTotal 側を 1 文字も触っていないのに、返る金額が変わります。計算をクラスの中に閉じ込めるというのは、この「直す場所が 1 か所で済む」状態を買う行為です。
要件
- Solution クラスに public static int productTotal(int price) を実装する
- Product クラスを定義して getPriceWithTax() で税込み価格を返す設計にする (税率 10% は TAX_RATE のような static final な定数で表現するのが望ましい)
- 戻り値は int 型。小数は (int) キャストで切り捨てる
入出力例
productTotal(100) → 110
productTotal(99) → 108
productTotal(3980) → 4378
productTotal(0) → 0