居酒屋で「ビールの値段いちいち書くの面倒すぎ!」となったので、
デフォルト引数 でクラス設計を改善!注文伝票を簡略化!
問題概要
前回と違う点は、ビールフェスでビールの注文が多くて、いちいち種類と値段を書くのが面倒になった点。
-
全員がソフトドリンクと食事を頼める。
-
20歳以上のお客さんだけがお酒(ビール含む)を頼める。
-
20歳未満がお酒を頼んだ場合は無効。
-
お酒(またはビール)を頼んだ後、以降の食事注文は 毎回200円引き になる。
-
ビールは値段が一律 500円。
注文票には「0」とだけ書かれ、値段は省略される。
店内の全てのお客さんの数と注文の回数、各注文をしたお客さんの番号とその内容が与えられるので、各お客さんの会計を求めよ。
入力例1
3 5
19
43
22
2 0
2 food 4333
1 0
2 0
1 food 4606
出力例1
4606
5133
0
✅OK例:昨日のコードに追加
class MinorCustomer {
constructor(){
this.bill = 0;
}
getBill(){
return this.bill;
}
orderSoftdrink(price) {
this.bill += price;
}
orderFood(price) {
this.bill += price;
}
orderAlcohol(price) {
//未成年はお酒禁止
}
orderBeer(){
//ビールもダメ
}
}
class AdultCustomer extends MinorCustomer {
constructor(){
super();
this.hasAlcohol = false;
}
orderFood(price){
super.orderFood(price);
if(this.hasAlcohol) this.bill -= 200;
}
orderAlcohol(price){
this.bill += price;
this.hasAlcohol = true;
}
orderBeer(){
this.bill += 500;
this.hasAlcohol = true;
}
}
const rl = require('readline').createInterface({input:process.stdin});
const lines = [];
rl.on('line', (input) => {
lines.push(input);
});
rl.on('close', () => {
const [N, K] = lines[0].split(' ').map(Number);
const ages = lines.slice(1, N+1).map(Number);
const orders = lines.slice(N+1);
const customers = ages.map(age => {
if (age < 20){
return new MinorCustomer(); // ⚠️ returnを忘れないで!
}
else {
return new AdultCustomer(); // ⚠️ returnを忘れないで!
}
})
for (const orderLine of orders){
const [numStr, category, priceStr] = orderLine.split(' ');
const num = Number(numStr) - 1;
const price = Number(priceStr);
const customer = customers[num];
if (category === 'softdrink'){
customer.orderSoftdrink(price);
}
else if (category === 'food'){
customer.orderFood(price);
}
else if (category === 'alcohol'){
customer.orderAlcohol(price);
}
else if(category === '0'){
customer.orderBeer();
}
}
const results = customers.map(c => c.getBill());
console.log(results.join('\n'));
});
前回のコードにビールの注文専用のメソッドを追加しただけ。
✨OK例:デフォルト引数
class MinorCustomer {
constructor(){
this.bill = 0;
}
getBill(){
return this.bill;
}
orderSoftdrink(price) {
this.bill += price;
}
orderFood(price) {
this.bill += price;
}
orderAlcohol(price = 500) {
//未成年はお酒禁止
}
}
class AdultCustomer extends MinorCustomer {
constructor(){
super();
this.hasAlcohol = false;
}
orderFood(price){
super.orderFood(price);
if(this.hasAlcohol) this.bill -= 200;
}
orderAlcohol(price = 500){
this.bill += price;
this.hasAlcohol = true;
}
}
const rl = require('readline').createInterface({input:process.stdin});
const lines = [];
rl.on('line', (input) => {
lines.push(input);
});
rl.on('close', () => {
const [N, K] = lines[0].split(' ').map(Number);
const ages = lines.slice(1, N+1).map(Number);
const orders = lines.slice(N+1);
const customers = ages.map(age => age >= 20 ? new AdultCustomer() : new MinorCustomer());
for (const orderLine of orders){
const [numStr, category, priceStr] = orderLine.split(' ');
const num = Number(numStr) - 1;
const price = Number(priceStr);
const customer = customers[num];
if (category === '0'){
customer.orderAlcohol();
}
else if (category === 'softdrink'){
customer.orderSoftdrink(price);
}
else if (category === 'food'){
customer.orderFood(price);
}
else if(category === 'alcohol'){
customer.orderAlcohol(price);
}
}
const results = customers.map(c => c.getBill());
console.log(results.join('\n'));
});
デフォルトでお酒の値段を500円で設定しているので、
引数を指定しなかった場合(ビール)は、
デフォルトの500円がpriceの値となり、
種類関係なくお酒が注文されたときの処理が行われる。
→ビール専用の関数を書かなくて済む!
あと、ビールフェスってことでビールが頻出なんだから、条件分岐でも先に判別した方がよさそうだってことで並び替えた。
📝まとめ:デフォルト引数
1️⃣デフォルト引数の 基本構文
function greet(name = 'Guest') {
console.log(`Hello, ${name}!`);
}
greet(); // Hello, Guest!
greet('Alice'); // Hello, Alice!
-
function func(param = デフォルト値)の形で指定。 - 引数を省略すると自動でデフォルト値が入る。
2️⃣ 特徴
-
関数(またはメソッド)の呼び出しで 引数が undefined のとき に適用される。
-
null は undefined ではないので注意!(null を渡すと null になる)
3️⃣ クラスのメソッドでも同じ
クラスのメソッドでも普通の関数と同じように設定できる。
class Sample {
say(message = 'Hi!') {
console.log(message);
}
}
const s = new Sample();
s.say(); // Hi!
s.say('Hello!'); // Hello!
4️⃣ 利点
- 共通処理を一つにまとめられる
今回のように「お酒とビールの処理は同じ。値段だけが違う」ならデフォルト値で一つにできる。
- 呼び出し側で省略できる
ビールのときは orderAlcohol() とだけ書けば OK。
- コードの重複を防げる
ビール専用メソッドや if を増やす必要がなくなる。
- 可読性が上がる
「引数がない場合はこれで進む」という意図が一目でわかる。
✅ まとめ(今回のコードに当てはめると)
orderAlcohol(price = 500)
-
普通のお酒:
orderAlcohol(800)→price = 800 -
ビール:
orderAlcohol()→priceが自動で500
だから、
「ビールは別メソッドにせず、お酒扱いにまとめられる」