1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

居酒屋で「ビールの値段いちいち書くの面倒すぎ!」となったので、
デフォルト引数 でクラス設計を改善!注文伝票を簡略化!


問題概要

前回と違う点は、ビールフェスでビールの注文が多くて、いちいち種類と値段を書くのが面倒になった点。


  • 全員がソフトドリンクと食事を頼める。

  • 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

だから、

「ビールは別メソッドにせず、お酒扱いにまとめられる」





僕の失敗談(´;ω;`)と解決法🐈

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?