chooseOption()은 addToCart() 내부에서 호출될 예정이며, 특정 상품에 대해서 옵션을 선택할 수 있게 해주는 역할을 수행한다.
바로 chooseOption()의 메서드 시그니처를 작성하자.
입력값 : 상품에 따라 선택할 수 있는 옵션이 다르므로, 상품을 입력값으로 받아와야 한다.
반환값 : 상품의 옵션을 나타내는 isBurgerSet, ketchup, hasStraw를 Setter를 통해 변경시켜주기만 하면 되므로, 반환값이 필요하지 않다.
접근 범위 : Cart 객체의 addToCart() 메서드 내에서만 호출될 것이므로 private로 지정한다.
의사코드를 작성해보자(instanceof 연산자를 활용해 product의 타입을 검사해 준다.)
여기에서도 다운캐스팅을 사용하였는데, 다운캐스팅을 사용한 이유는 앞서 설명했던 것과 동일하다.
if문에서 return을 써야할지 말지는 메서드의 반환타입을 보고 결정하자 특정 반환타입이 존재하는 경우에는 return 존재해야하고 반환타입이 void인 경우 return이 없거나 'return;' 이어야 한다.
composeSet()은 햄버거 세트를 구성해 주는 역할을 한다.
사용자에게 선택 가능한 사이드 메뉴를 보여주고, 사용자가 선택한 사이드 메뉴를 입력받기
사용자가 선택한 사이드 메뉴의 옵션을 보여주고, 사용자가 선택한 옵션을 입력받기
사용자에게 선택 가능한 음료 메뉴를 보여주고, 사용자가 선택한 음료 메뉴를 입력받기
사용자가 선택한 음료 메뉴의 옵션을 보여주고, 사용자가 선택한 옵션을 입력받기
사용자가 선택한 대로 세트를 구성해서 햄버거 세트를 반환하기
composeSet()의 의사코드이다.
위의 의사코드를 보면, 사이드, 음료 메뉴를 부분적으로 보여주어야 하므로 Menu 인스턴스를 필드로 정의할 필요가 있다.
작성을 하고 나면 이런식으로 오류가 발생한다.
printSide(), printDrinks() → 접근 범위가 private이기 때문에 발생한 에러이다.
간단한 수정 사항이므로, 이 둘의 접근 제어자를 protected로 변경
현재 Cart와 Menu는 같은 패키지에 있기 때문에 protected로 바꾸어주어도 접근이 가능합니다.
new BurgerSet(…) → [2-2-5 BurgerSet 생성자 수정]에서 설명
햄버거 세트는 productRepository에 미리 등록되어 있는 상품이 아니므로, id가 필요하지 않다. 따라서, new BurgerSet(…)을 통해 햄버거 세트 인스턴스를 생성할 때 굳이 id를 인자로 전달하지 않아도 된다.
BurgerSet의 생성자의 매개변수 목록에서 아래와 같이 int id를 삭제해 주고, super()의 인자에서도 id를 삭제
이렇게 하면 또 super(...)에서 빨간 밑줄이 생긴다. 이는 super()가 가리키는 Product의 생성자 중 String name, int price, int kcal를 인자로 받는 생성자가 없기 때문에 발생하는 문제이다.
따라서, String name, int price, int kcal를 인자로 받는 생성자를 추가하여 오버로딩해 주면 문제는 해결된다.
옵션까지 선택이 완료되고 나면, 상품을 추가하기 전에 먼저 product가 햄버거인지, 햄버거라면 옵션이 세트인지 검사해서 세트일 경우 세트를 구성해 주는 메서드인 composeSet()을 호출해주어야 한다.
composeSet()에서 Hamburger 타입의 인스턴스를 인자로 받고 있으니, product를 Hamburger 타입으로 product를 다운캐스팅하여 전달하면서 composeSet()을 호출해 준다.
composeSet()은 햄버거 세트를 구성하여 반환해 주므로, composeSet()의 반환값을 product에 할당해 준다.
배열의 길이를 1만큼 확장한 새로운 배열을 만듭니다.
기존 배열의 요소를 새로운 배열로 복사합니다.
마지막 요소에 새로운 product를 할당해 줍니다.
items에 새로운 배열을 할당해 줍니다.
printSides()와 printDrinks()를 재사용하면서 이를 구현하려면 printSides()와 printDrinks() 내에서 조건을 통해 코드 실행 흐름을 분기시켜 준 다음, 전체 메뉴를 출력할 때와 세트를 구성하면서 부분적으로 메뉴를 출력할 때의 코드를 다르게 작성해주어야 한다.
메뉴에서 사이드와 음료의 가격을 출력하는 코드는 Menu 클래스의 printEachMenu()에 있다. printEachMenu()의 코드를 아래와 같이 수정.
printEachMenu()는 printHamburgers(), printDrinks(), printSides()에서 호출되므로, 이들에도 매개변수 printPrice를 추가해 준 다음, printEachMenu의 인자로 전달해주어야 한다.
printHamburgers(), printDrinks(), printSides()를 호출하는 코드에도 인자를 입력. 먼저, 전체 메뉴를 출력하는 printMenu()에는 true를 넣어주면 된다.
그리고, composeSet()의 printSides()와 printDrinks()를 호출하는 코드에는 false를 인자로 넣어줍니다.
Integer.parseInt()는 입력 문자가 +가 아닌 경우에 입력을 숫자로 바꾸기 위해 사용.