7. 메서드 재정의
상위 클래스에 정의된 메서드가 하위클래스에 맞지 않을 때
하위클래스에서 재정의하는 것= 오버라이드
이름, 반환값, 매개변수는 동일
package inheritance;
public class Membership {
private int memberId;
protected String memberName;
protected int bonusPoint;
protected double bonusRatio;
protected String membership;
public Membership(int memberId, String memberName) {
this.memberId=memberId;
this.memberName=memberName;
membership="Silver";
bonusRatio=0.01;
}
public int calcPrice(int price) {
bonusPoint+=price*bonusRatio;
return price;
}
}
package inheritance;
public class GoldMembership extends Membership{
private double salesRatio;
// 디폴트가 없으면 Add Constructor를 하도록 창이 뜸
public GoldMembership(int anything, String anything2) {
super(anything, anything2); // 상위 클래스 생성자를 호출
membership="Gold";
bonusRatio=0.05;
salesRatio=0.05;
}
@Override //annotation compiler에게 재정의된 메서드라는 것을 알려줌. 없으면 다른 메서드로 인식
public int calcPrice(int price) {
bonusPoint+=price*bonusRatio;
price-=price*salesRatio;
return price;
}
public double getSalesRatio() {
return salesRatio;
}
public void setSalesRatio(double salesRatio) {
this.salesRatio = salesRatio;
}
}
package inheritance;
public class MembershipTest {
public static void main(String[] args) {
Membership memberLee= new Membership(1002,"Lee");
GoldMembership memberKim= new GoldMembership(1010,"Kim");
Membership memberPark= new GoldMembership(888,"Park");
int price=10000;
int memberPrice=memberLee.calcPrice(price);
int goldPrice=memberKim.calcPrice(price); //GoldMembership의 override된 calcPrice를 호출함
int parkPrice=memberPark.calcPrice(price);
System.out.println(memberPrice); //10000
System.out.println(goldPrice); //95000
System.out.println(parkPrice); //95000
}
}
parkPrice == 95000인 이유 🙄
메서드나 멤버변수가 불리는 기준은 자료형 -> 멤버십으로 선언된 memberPark은 멤버십으로 불려야 되는 게 맞는데
c++에서 나온 자바는 c++의 가상함수 개념과 같은 가상 메서드의 개념이 적용되어 모든 메서드가 가상메서드임
-> 가상 메서드 방식에 의해 골드 회원 인스턴스의 메서드가 호출됨
private으로 선언된 salesRatio 변수에는 다운캐스팅을 하지 않으면 접근이 불가하지만 메서드는 골드의 메서드를 불러온다????????? 맞아???????
가상메서드
프로그램에서 어떤 객체의 변수나 메서드의 참조는 그 타입에 따라 이루어짐
가상 메서드는 타입과 상관없이 실제 생성된 인스턴스의 메서드가 호출됨
가상메서드를 통해서 다형성을 구현할 수 있음
하나의 코드가 여러 자료형으로 구현됨
객체 지향 프로그래밍의 유연성, 재활용성, 유지보수성의 기본이 됨
package polymorphism;
import java.util.ArrayList;
import inheritance.GoldMembership; // ctrl + shift + o
import inheritance.Membership;
public class PolymorphismTest {
public static void main(String[] args) {
ArrayList<Membership> memberList = new ArrayList<Membership>();
Membership memberLee = new Membership(1001,"Lee");
Membership memberKim= new GoldMembership(1002,"Kim");
// Lee와 Kim 모두 멤버십으로 선언되었기 때문에 memberList에 넣을 수 있음
memberList.add(memberLee);
memberList.add(memberKim);
int price=1000;
for(Membership member:memberList) {
int newPrice = member.calcPrice(price);
// 각 멤버십 클래스에서 calcPrice 메서드만 오버라이드하면 member 인스턴스에 정의된 calcPrice에 따라서
// 하나의 코드에 의해서 여러 구현(여러 등급의 멤버십의 가격에 따른 가격을 계산)이 가능함
// 다형성=>인스턴스에 따라서 다른 메서드가 호출됨
System.out.println(newPrice);
}
}
}
상속을 사용하게 되면 클래스간 결합도가 증가하기 때문에 클래스간의 상하관계가 명확한 경우만 상속을 사용함