오늘은 상속, 추상화, 캡슐화, 다형성을 모두 배웠고, 그것을 한반에 적용한 카페 키오스크 프로그래밍을 했다. 일단 개념만 정리하면 이렇다.
추상화는: 공통점을 뽑아 내는 것이고,
상속은 다중상속이 안되고 단일 상속만 가능하다.
하지만 인터페이슨 다중 구현이 가능하다.
추상메서드 | 인터페이스 |
일반 클래스(o) | 일반 메서드(x) |
단일 상속 | 다중 구현(o) |
표로 나타내자면 이렇다.
다형성이란 -> 같은 참조변수를 사용할 때 다양한 결과를 가지는 것을 의미하고,
상위 클래스 타입의 참조변수를 통해서 하위 클래스의 객체를 참조할 수 있도록 허용한 것이다.
ex)
GirlFriend friedn = new GirlFriend();
Friend friend = new GirlFriend();
즉 위에 클래스가 Friedn에게 상속당해있다면, 다형성을 구현할 수 있는 것이다.
이 코드는 클래스의 독립성을 높혀주는데 사용된다.
<coffee>
package MiniProject.product;
import java.util.Scanner;
public class Coffee extends Products{
private boolean shoot;
public Coffee(int id, String name, int price, boolean shoot) {
super(id, name, price);
this.shoot = shoot;
}
public void setShoot(boolean shoot) {
this.shoot = shoot;
}
@Override
public void applyOption() {
System.out.println("샷을 추가하시겠습니까? (1)_예 (2)_아니오");
Scanner sc = new Scanner(System.in);
int optioin = Integer.parseInt(sc.nextLine());
if(optioin==1)setShoot(true);
}
@Override
public String getOptionToString() {
return shoot ? "(샷 추가)" : "";
}
}
<tea>
package MiniProject.product;
import java.util.Scanner;
public class Tea extends Products{
private boolean teaback;
public Tea(int id, String name, int price, boolean teaback) {
super(id, name, price);
this.teaback = teaback;
}
public void setTeaback(boolean teaback) {
this.teaback = teaback;
}
@Override
public void applyOption() {
System.out.println("티백을 제거하시겠습니까? (1)_예 (2)_아니오");
Scanner sc = new Scanner(System.in);
int optioin = Integer.parseInt(sc.nextLine());
if(optioin==1)setTeaback(true);
}
@Override
public String getOptionToString() {
return teaback ? "(티백 제거)" : "";
}
}
위와같이 커피 클래스와 티 클래스가 공통요소가 많은데 따로 일일이 써줄경우 중복코드가 발생하고, 따로따로 분리된 객체라면 다형성을 구현하기 힘들다.
<product>
package MiniProject.product;
public abstract class Products {
// 커피와 차의 공통 정보를 가지고 있어야 한다.
// 이름, 가격 + id (Primary Key)
private int id;
private String name;
private int price;
public Products(int id, String name, int price) {
this.id = id;
this.name = name;
this.price = price;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public int getPrice() {
return price;
}
public abstract void applyOption();
public abstract String getOptionToString();
}
Like this 상품이라는 추상 클래스를 만들어 커피와 티에 상속을 시켜놓으면 커피와 티의 코드를 고치고, 사용자에 따라서 커피를 이용하거나 티를 이용할때도 Products클래스로 묶어서 main코드를 수정할 필요가 없다.
package MiniProject;
import java.util.Scanner;
public class discount implements DiscountCondition{
private final int discount = 500;
public int discount(int price){
if(checkDiscountCondition()) return price - discount;
else return price;
}
// 할인 조건을 물어보는 메서드
public boolean checkDiscountCondition() {
Scanner scanner = new Scanner(System.in);
System.out.println("백엔드 수강생이십니까? (1)_예 (2)_아니오");
String input = scanner.nextLine();
if (input.equals("1")) return true;
else return false;
}
public int getDiscount() {
return discount;
}
}
이는 다음과 같은 코드로도 확인 할 수 있다.
private void order(Products selectedProduct) {
int price = new discount.discount(selectedProduct.getprice());
System.out.println("주문이 완료되었습니다. ");
System.out.printf(
"주문 상품 : %s %s\n",
selectedProduct.getName(), selectedProduct.getOptionToString()
);
System.out.printf("가격 : %d\n", price);
}
만약 구현 메서드에서 int price에 값을 넣을 때 discount의 조건이 바뀌어 다른 클래스로 만들어 주었을 때 discount클래스가 아닌 order에 대한 코드를 수정해야 한다. 그러니 공통적인 요소가 많은 클래스가 있을 때는 하나로 묶어 인터페이스 혹은 추상화 클래스로 만들고
private void order(Products selectedProduct) {
int price = discountCondition.discount(selectedProduct.getPrice());
System.out.println("주문이 완료되었습니다. ");
System.out.printf(
"주문 상품 : %s %s\n",
selectedProduct.getName(), selectedProduct.getOptionToString()
);
System.out.printf("가격 : %d\n", price);
}
상위클래스를 참조변수로 하여금 사용 하게 해야한다는 것이다. 이것이 의존성에 대한 내용이다.