메서드 재정의하기(overring)
하위 클래스에서 메서드 재정의 하기
- 오버라이딩(overriding) : 상위 클래스에 정의된 메서드의 구현 내용이 하위 클래스에서 구현할 내용과 맞지 않는 경우 하위 클래스에서 동일한 이름의 메서드를 재정의 할 수 있음
- VIPCustomer 클래스의 calcPrice()는 할인율이 적용되지 않음
- 재정의 하여 구현해야 함
VIPCustomer.java
@Override
public int calcPrice(int price) {
bonusPoint += price * bonusRatio;
return price - (int)(price * salesRatio);
}
@overriding 애노테이션 (annotation)
- 애노테이션은 원래 주석이라는 의미
- 컴파일러에게 특별한 정보를 제공해주는 역할
- @overriding 애노테이션은 재정의 된 메서드라는 의미로 선언부가 기존의 메서드와 다른 경우 에러가 남
형 변환과 오버라이딩 메서드 호출
Customer vc = new VIPCustomer();
vc 변수의 타입은 Customer지만 인스턴스의 타입은 VIPCustomer 임
자바에서는 항상 인스턴스의 메서드가 호출 됨 (가상메서드의 원리)
자바의 모든 메서드는 가상 메서드(virtual method) 임
CustomerTest.java
public class CustomerTest {
public static void main(String[] args) {
Customer customerLee = new Customer(10010, "이순신");
customerLee.bonusPoint = 1000;
System.out.println(customerLee.showCustomerInfo());
VIPCustomer customerKim = new VIPCustomer(10020, "김유신");
customerKim.bonusPoint = 10000;
System.out.println(customerKim.showCustomerInfo());
int priceLee = customerLee.calcPrice(10000);
int priceKim = customerKim.calcPrice(10000);
System.out.println(customerLee.showCustomerInfo() + " 지불금액은 " + priceLee + "원 입니다.");
System.out.println(customerKim.showCustomerInfo() + " 지불금액은 " + priceKim + "원 입니다.");
Customer customerNo = new VIPCustomer(10030, "나몰라");
customerNo.bonusPoint = 10000;
int priceNo = customerNo.calcPrice(10000);
System.out.println(customerNo.showCustomerInfo() + " 지불금액은 " + priceNo + "원 입니다.");
}
}
메서드 재정의와 가상 메서드 원리
메서드는 어떻게 호출되고 실행 되는가?
- 메서드(함수)의 이름은 주소값을 나타냄
- 메서드는 명령어의 set 이고 프로그램이 로드되면 메서드 영역(코드 영역)에 명령어 set이 위치
- 해당 메서드가 호출 되면 명령어 set 이 있는 주소를 찾아 명령어가 실행됨
- 이때 메서드에서 사용하는 변수들은 스택 메모리에 위치 하게됨
- 따라서 다른 인스턴스라도 같은 메서드의 코드는 같으므로 같은 메서드가 호출됨
- 인스턴스가 생성되면 변수는 힙 메모리에 따로 생성되지만, 메서드 명령어 set은 처음 한번만 로드 됨
public class TestMethod {
int num;
void aaa() {
System.out.println("aaa() 호출");
}
public static void main(String[] args) {
TestMethod a1 = new TestMethod();
a1.aaa();
TestMethod a2 = new TestMethod();
a2.aaa();
}
}
가상 메서드의 원리
- 가상 메서드 테이블(vitual method table)에서 해당 메서드에 대한 address를 가지고 있음
- 재정의된 경우는 재정의 된 메서드의 주소를 가리킴
다형성(polymorphism) 이란?
- 하나의 코드가 여러 자료형으로 구현되어 실행되는 것
- 같은 코드에서 여러 다른 실행 결과가 나옴
- 정보은닉, 상속과 더불어 객체지향 프로그래밍의 가장 큰 특징 중 하나임
- 다형성을 잘 활용하면 유연하고 확장성있고, 유지보수가 편리한 프로그램을 만들수 있음
다형성의 예
class Animal{
public void move() {
System.out.println("동물이 움직입니다.");
}
public void eating() {
}
}
class Human extends Animal{
public void move() {
System.out.println("사람이 두발로 걷습니다.");
}
public void readBooks() {
System.out.println("사람이 책을 읽습니다.");
}
}
class Tiger extends Animal{
public void move() {
System.out.println("호랑이가 네 발로 뜁니다.");
}
public void hunting() {
System.out.println("호랑이가 사냥을 합니다.");
}
}
class Eagle extends Animal{
public void move() {
System.out.println("독수리가 하늘을 날아갑니다.");
}
public void flying() {
System.out.println("독수리가 날개를 쭉 펴고 멀리 날아갑니다");
}
}
public class AnimalTest {
public static void main(String[] args) {
Animal hAnimal = new Human();
Animal tAnimal = new Tiger();
Animal eAnimal = new Eagle();
AnimalTest test = new AnimalTest();
test.moveAnimal(hAnimal);
test.moveAnimal(tAnimal);
test.moveAnimal(eAnimal);
ArrayList<Animal> animalList = new ArrayList<Animal>();
animalList.add(hAnimal);
animalList.add(tAnimal);
animalList.add(eAnimal);
for(Animal animal : animalList) {
animal.move();
}
}
public void moveAnimal(Animal animal) {
animal.move();
}
}
다형성을 사용하는 이유?
- 다른 동물을 추가하는 경우
- 상속과 메서드 재정의를 활용하여 확장성 있는 프로그램을 만들 수 있음
- 그렇지 않는 경우 많은 if-else if문이 구현되고 코드의 유지보수가 어려워짐
- 상위 클래스에서는 공통적인 부분을 제공하고 하위 클래스에서는 각 클래스에 맞는 기능 구현
- 여러 클래스를 하나의 타입(상위 클래스)으로 핸들링 할 수 있음
다형성을 활용한 멤버십 프로그램 확장
- 일반 고객과 VIP 고객 중간 멤버십 만들기
- GOLD 고객 등급을 만들고 혜택은 다음과 같다
- 제품을 살때는 10프로를 할인해준다
- 보너스 포인트는 2%를 적립해준다
- 고객이 늘어 일반 고객보다는 많이 구매하고 VIP보다는 적게 구매하는 고객에게도 해택을 주기로 했다.
GoldCustomer.java
public class GoldCustomer extends Customer{
double saleRatio;
public GoldCustomer(int customerID, String customerName){
super(customerID, customerName);
customerGrade = "GOLD";
bonusRatio = 0.02;
saleRatio = 0.1;
}
public int calcPrice(int price){
bonusPoint += price * bonusRatio;
return price - (int)(price * saleRatio);
}
}
VIPCustomer.java
//showCustomerInfo() 재정의
public String showCustomerInfo(){
return super.showCustomerInfo() + " 담당 상담원 번호는 " + agentID + "입니다";
}
CustomerTest.java
public class CustomerTest {
public static void main(String[] args) {
ArrayList<Customer> customerList = new ArrayList<Customer>();
Customer customerLee = new Customer(10010, "이순신");
Customer customerShin = new Customer(10020, "신사임당");
Customer customerHong = new GoldCustomer(10030, "홍길동");
Customer customerYul = new GoldCustomer(10040, "이율곡");
Customer customerKim = new VIPCustomer(10050, "김유신", 12345);
customerList.add(customerLee);
customerList.add(customerShin);
customerList.add(customerHong);
customerList.add(customerYul);
customerList.add(customerKim);
System.out.println("====== 고객 정보 출력 =======");
for( Customer customer : customerList){
System.out.println(customer.showCustomerInfo());
}
System.out.println("====== 할인율과 보너스 포인트 계산 =======");
int price = 10000;
for( Customer customer : customerList){
int cost = customer.calcPrice(price);
System.out.println(customer.getCustomerName() +" 님이 " + + cost + "원 지불하셨습니다.");
System.out.println(customer.getCustomerName() +" 님의 현재 보너스 포인트는 " + customer.bonusPoint + "점입니다.");
}
}
}
'|Backend.DevLog > JAVA' 카테고리의 다른 글
23. Java - 인터페이스, DAO, 인터페이스요소 (0) | 2022.07.07 |
---|---|
22. Java - 추상 클래스(abstract class) 구현, 템플릿 메서드 패턴 (0) | 2022.07.07 |
19. Java - 상속 (0) | 2022.07.01 |
18. Java - array (배열), 2차원배열, ArrayList (0) | 2022.06.30 |
17. Java - static변수, static 메서드 , 싱글톤패턴 (0) | 2022.06.30 |
댓글