Closed chldbtjd2272 closed 4 years ago
재귀적 타입 한정을 이용하는 제네릭타입을 사용하면 추상메서드 self 를 지원함으로써 하위클래스에서 형변환 하지 않고도 상위타입에서 구현한 메서드를 연쇄적으로 호출할 수 있는데,
public abstract class PayCard {
final Set<Benefit> benefits;
PayCard(Builder<?> builder) {
benefits = builder.benefits.clone();
}
public enum Benefit {
POINT("포인트"), SALE("할인"), SUPPORT("연회비지원");
Benefit(String benefit) {
}
}
abstract static class Builder<T extends Builder<T>> { // 재귀적 타입한정
EnumSet<Benefit> benefits = EnumSet.noneOf(Benefit.class);
public T addBenefit(Benefit benefit) {
this.benefits.add(benefit);
return self();
}
abstract PayCard build();
protected abstract T self();
}
}
이거 예전에 민형이가 자신의 메서드를 호출하는 메서드는 재정의가능하게 만들지 말라는거 설명했을 때 그 경우를 활용한 예? 같더라고 ,,? 상위타입의 addBenefit 메서드는 자기 자신의 self 메서드를 호출하고(추상메서드니까 괜찮지만) 하위타입에서는 상위타입의 addBenefit메서드를 호출하지만 self 메서드는 자기가 재구현한 self 메서드를 호출하는 것을 이용한거같아서 신기하더랑
이 추상클래스의 하위타입인 LottePayCard는 PayCard의 Builder를 상속한 Builder를 구현함으로써, 상위타입에서 말한 "Builder
public class LottePayCard extends PayCard {
private final Sale sale;
LottePayCard(Builder builder) {
super(builder);
sale = builder.sale;
}
public enum Sale {
LOTTE_WORLD("롯데월드"), LOTTE_DEPT("롯데백화점");
Sale(String sale) {
}
}
public static class Builder extends PayCard.Builder<Builder> {
private final Sale sale;
public Builder(Sale sale) {
this.sale = sale;
}
@Override
LottePayCard build() {
return new LottePayCard(this);
}
@Override
protected Builder self() {
return this;
}
}
}
글고 재귀적 타입한정을 안쓰면 불가능 하다기보다는 하위클래스를 구현할 때 self 메서드에 자기자신(Builder)를 반환하도록 강제하기 위한거 아닐까 ,,? 재귀적타입한정을 쓰지 않아도 제대로 PayCard.Builder
@DisplayName("시뮬레이트한 셀프타입 관용구")
@Test
void simulate() {
LottePayCard lottePayCard = new LottePayCard.Builder(LOTTE_DEPT)
.addBenefit(PayCard.Benefit.POINT)
.build();
}
엌ㅋㅋㅋㅋㅋ나랑 같은질문이었군,,, 낼 같이보고 지워용
180p 시뮬레이트한 셀프관용구에 대한 설명이 나오는데, 이게 2장의 Builder패턴 pizza를 상속받은 nypizza 빌더패턴에 대한 이야기야, 이거 한번 구현해보고 실제로 왜 재귀적 타입한정을 써야 이런 구현들이 가능한지, 재귀적 타입한정을 안쓰면 왜 불가능한지에 대해 설명해줬으면 좋겠어