{"componentChunkName":"component---src-containers-post-index-tsx","path":"/backend/object/chapter12/다형성/","result":{"pageContext":{"next":{"id":"45d49f32-c00f-5da9-8b11-e6b443efa26c","html":"<p>상속</p>\n<ul>\n<li>부모 클래스와 자식 클래스 사이의 의존성은 컴파일타임에 해결</li>\n<li>is-a 관계</li>\n<li>클래스 사이의 정적 관계</li>\n</ul>\n<p>합성</p>\n<ul>\n<li>부모 클래스와 자식 클래스 사이의 의존성은 런타임에 해결</li>\n<li>has-a 관계</li>\n<li>객체 사이의 동적 관계</li>\n</ul>\n<p>코드 재사용을 위해서는 객체 합성이 클래스 상속보다 더 좋은 방법이다.</p>\n<h2 id=\"-111-상속을-합성으로-변경하기\" style=\"position:relative;\"><a href=\"#-111-%EC%83%81%EC%86%8D%EC%9D%84-%ED%95%A9%EC%84%B1%EC%9C%BC%EB%A1%9C-%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0\" aria-label=\" 111 상속을 합성으로 변경하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 11.1 상속을 합성으로 변경하기</h2>\n<p>상속을 남용할 때 직면하는 세 가지 문제</p>\n<ol>\n<li>불필요한 인터페이스 상속 문제</li>\n<li>메서드 오버라이딩의 오작용 문제</li>\n<li>부모 클래스와 자식 클래스의 동시 수정 문제</li>\n</ol>\n<h3 id=\"-1111-불필요한-인터페이스-상속-문제-javautilproperties와-javautilstack\" style=\"position:relative;\"><a href=\"#-1111-%EB%B6%88%ED%95%84%EC%9A%94%ED%95%9C-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EC%83%81%EC%86%8D-%EB%AC%B8%EC%A0%9C-javautilproperties%EC%99%80-javautilstack\" aria-label=\" 1111 불필요한 인터페이스 상속 문제 javautilproperties와 javautilstack permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 11.1.1 불필요한 인터페이스 상속 문제: java.util.Properties와 java.util.Stack</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class Properties {\n    private Hashtable&lt;String, String&gt; properties = new Hashtable&lt;&gt;();\n\n    public String setProperty(String key, String value) {\n        return properties.put(key, value);\n    }\n\n    public String getProperty(String key) {\n        return properties.get(key);\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>더 이상 불필요한 <code>Hashtable</code>의 오퍼레이션들이 퍼블릭 인터페이스를 오염시키지 않는다.</li>\n<li><code>Stack</code> 또한 <code>Vector</code>의 인스턴스 변수를 <code>Stack</code> 클래스의 인스턴스 변수로 선언함으로써 합성 관계로 변경할 수 있다.</li>\n</ul>\n<h3 id=\"-1112-메서드-오버라이딩의-오작용-문제-instrumentedhashset\" style=\"position:relative;\"><a href=\"#-1112-%EB%A9%94%EC%84%9C%EB%93%9C-%EC%98%A4%EB%B2%84%EB%9D%BC%EC%9D%B4%EB%94%A9%EC%9D%98-%EC%98%A4%EC%9E%91%EC%9A%A9-%EB%AC%B8%EC%A0%9C-instrumentedhashset\" aria-label=\" 1112 메서드 오버라이딩의 오작용 문제 instrumentedhashset permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 11.1.2 메서드 오버라이딩의 오작용 문제: InstrumentedHashSet</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic class InstrumentedHashSet&lt;E&gt; implements Set&lt;E&gt; {\n    \n    private static final int addCount = 0;\n    \n    private final Set&lt;E&gt; set;\n\n    ... // Overriding\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>HashSet</code>에 대한 구현 결합도는 제거하면서 퍼블릭 인터페이스는 그대로 상속</li>\n</ul>\n<p>포워딩</p>\n<ul>\n<li><code>Set</code>의 오버레이션을 오버라이딩한 인스턴스 메서드에서 내부의 <code>HashSet</code> 인스턴스에게 동일한 메서드 호출을 그대로 전달</li>\n<li>동일한 메서드를 호출하기 위해 추가된 메서드를 <strong>포워딩 메서드</strong>라고 부른다.</li>\n<li>기존 클래스의 인터페이스를 그대로 외부에 제공하면서 구현에 대한 결합 없이 일부 작동 방식을 변경하고 싶은 경우에 유용한 기법</li>\n</ul>\n<h3 id=\"-1113-부모-클래스와-자식-클래스의-동시-수정-문제-personalplaylist\" style=\"position:relative;\"><a href=\"#-1113-%EB%B6%80%EB%AA%A8-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%EC%9E%90%EC%8B%9D-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%9D%98-%EB%8F%99%EC%8B%9C-%EC%88%98%EC%A0%95-%EB%AC%B8%EC%A0%9C-personalplaylist\" aria-label=\" 1113 부모 클래스와 자식 클래스의 동시 수정 문제 personalplaylist permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 11.1.3 부모 클래스와 자식 클래스의 동시 수정 문제: PersonalPlaylist</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class PersonalPlaylist {\n\n    private Playlist playlist = new Playlist();\n\n    public void append(Song song) {\n        playlist.append(song);\n    }\n\n    public void remove(Song song) {\n        playlist.getTracks().remove(song);\n        playlist.getSingers().remove(song.getSinger());\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>향후에 <code>Playlist</code>의 내부 구현을 변경하더라도 파급효과를 최대한 <code>PersonalPlaylist</code> 내부로 캡슐화할 수 있다.</li>\n</ul>\n<p>몽키 패치</p>\n<ul>\n<li>현재 실행 중인 환경에만 영향을 미치도록 지역적으로 코드를 수정하거나 확장하는 것</li>\n</ul>\n<h2 id=\"-112-상속으로-인한-조합의-폭발적인-증가\" style=\"position:relative;\"><a href=\"#-112-%EC%83%81%EC%86%8D%EC%9C%BC%EB%A1%9C-%EC%9D%B8%ED%95%9C-%EC%A1%B0%ED%95%A9%EC%9D%98-%ED%8F%AD%EB%B0%9C%EC%A0%81%EC%9D%B8-%EC%A6%9D%EA%B0%80\" aria-label=\" 112 상속으로 인한 조합의 폭발적인 증가 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 11.2 상속으로 인한 조합의 폭발적인 증가</h2>\n<ol>\n<li>하나의 기능을 추가하거나 수정하기 위해 불필요하게 많은 수의 클래스를 추가하거나 수정해야 한다.</li>\n<li>단일 상속만 지원하는 언어에서는 상속으로 인해 오히려 중복 코드의 양이 늘어날 수 있다.</li>\n</ol>\n<h3 id=\"-1121-기본-정책과-부가-정책-조합하기\" style=\"position:relative;\"><a href=\"#-1121-%EA%B8%B0%EB%B3%B8-%EC%A0%95%EC%B1%85%EA%B3%BC-%EB%B6%80%EA%B0%80-%EC%A0%95%EC%B1%85-%EC%A1%B0%ED%95%A9%ED%95%98%EA%B8%B0\" aria-label=\" 1121 기본 정책과 부가 정책 조합하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 11.2.1 기본 정책과 부가 정책 조합하기</h3>\n<p>기본 정책</p>\n<ul>\n<li>가입자의 통화 정보 기반</li>\n<li>일반 요금제, 심야 할인 요금제</li>\n</ul>\n<p>부가 정책</p>\n<ul>\n<li>통화량과 무관하게 기본 정책에 선택적으로 추가할 수 있는 요금 방식</li>\n<li>세금 정책, 기본 요금 할인 정책</li>\n<li>기본 정책의 계산 결과에 적용</li>\n<li>선택적으로 적용 가능</li>\n<li>조합 가능</li>\n<li>임의의 순서로 적용 가능</li>\n</ul>\n<h3 id=\"-1122-상속을-이용해서-기본-정책-구현하기\" style=\"position:relative;\"><a href=\"#-1122-%EC%83%81%EC%86%8D%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%B4%EC%84%9C-%EA%B8%B0%EB%B3%B8-%EC%A0%95%EC%B1%85-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0\" aria-label=\" 1122 상속을 이용해서 기본 정책 구현하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 11.2.2 상속을 이용해서 기본 정책 구현하기</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic abstract class Phone {\n\n    private List&lt;Call&gt; calls = new ArrayList&lt;&gt;();\n\n    public Money calculateFee() {\n        Money result = Money.ZERO;\n\n        for (Call call : calls) {\n            result = result.plus(calculateCallFee(call));\n        }\n\n        return result;\n    }\n\n    protected abstract Money calculateCallFee(Call call);\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic class RegularPhone extends Phone {\n\n    private final Money amount;\n\n    private final Duration seconds;\n\n    @Override\n    protected Money calculateCallFee(Call call) {\n        return amount.times((double) call.getDuration().getSeconds() / seconds.getSeconds());\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic class NightlyDiscountPhone extends Phone {\n\n    private static final int LATE_NIGHT_HOUR = 22;\n\n    private final Money nightlyAmount;\n\n    private final Money regularAmount;\n\n    private final Duration seconds;\n\n    @Override\n    protected Money calculateCallFee(Call call) {\n        if (call.getFrom().getHour() &gt;= LATE_NIGHT_HOUR) {\n            return nightlyAmount.times((double) call.getDuration().getSeconds() / seconds.getSeconds());\n        }\n        return regularAmount.times((double) call.getDuration().getSeconds() / seconds.getSeconds());\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>기본 정책으로만 요금 계산</li>\n</ul>\n<h3 id=\"-1123-기본-정책에-세금-정책-조합하기\" style=\"position:relative;\"><a href=\"#-1123-%EA%B8%B0%EB%B3%B8-%EC%A0%95%EC%B1%85%EC%97%90-%EC%84%B8%EA%B8%88-%EC%A0%95%EC%B1%85-%EC%A1%B0%ED%95%A9%ED%95%98%EA%B8%B0\" aria-label=\" 1123 기본 정책에 세금 정책 조합하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 11.2.3 기본 정책에 세금 정책 조합하기</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class TaxableRegularPhone extends RegularPhone {\n\n    private final double taxRate;\n\n    public TaxableRegularPhone(Money amount, Duration seconds, double taxRate) {\n        super(amount, seconds);\n        this.taxRate = taxRate;\n    }\n\n    @Override\n    public Money calculateFee() {\n        Money fee = super.calculateFee();\n        return fee.plus(fee.times(taxRate));\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>결합도가 높아진다.</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic abstract class Phone {\n\n    private List&lt;Call&gt; calls = new ArrayList&lt;&gt;();\n\n    public Money calculateFee() {\n        Money result = Money.ZERO;\n\n        for (Call call : calls) {\n            result = result.plus(calculateCallFee(call));\n        }\n\n        return afterCalculated(result);\n    }\n\n    protected abstract Money calculateCallFee(Call call);\n    \n    protected abstract Money afterCalculated(Money fee);\n}\n</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic class RegularPhone extends Phone {\n\n    private final Money amount;\n\n    private final Duration seconds;\n\n    @Override\n    protected Money calculateCallFee(Call call) {\n        return amount.times((double) call.getDuration().getSeconds() / seconds.getSeconds());\n    }\n\n    @Override\n    protected Money afterCalculated(Money fee) {\n        return fee;\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic class NightlyDiscountPhone extends Phone {\n\n    private static final int LATE_NIGHT_HOUR = 22;\n\n    private final Money nightlyAmount;\n\n    private final Money regularAmount;\n\n    private final Duration seconds;\n\n    @Override\n    protected Money calculateCallFee(Call call) {\n        if (call.getFrom().getHour() &gt;= LATE_NIGHT_HOUR) {\n            return nightlyAmount.times((double) call.getDuration().getSeconds() / seconds.getSeconds());\n        }\n        return regularAmount.times((double) call.getDuration().getSeconds() / seconds.getSeconds());\n    }\n\n    @Override\n    protected Money afterCalculated(Money fee) {\n        return fee;\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>부모 클래스에 추상 메서드를 추가하면 꽤나 번거로워진다.</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic abstract class Phone {\n\n    private List&lt;Call&gt; calls = new ArrayList&lt;&gt;();\n\n    public Money calculateFee() {\n        Money result = Money.ZERO;\n\n        for (Call call : calls) {\n            result = result.plus(calculateCallFee(call));\n        }\n\n        return afterCalculated(result);\n    }\n\n    protected Money afterCalculated(Money fee) {\n        return fee;\n    }\n\n    protected abstract Money calculateCallFee(Call call);\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>기본 구현을 함께 제공하면 오버라이딩할 필요가 없다.</li>\n<li>훅 메서드(hook method)</li>\n<li>추상 메서드와 동일하게 자식 클래스에서 오버라이딩할 의도로 메서드를 추가했지만 편의를 위해 기본 구현을 제공하는 메서드</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class TaxableRegularPhone extends RegularPhone {\n\n    private final double taxRate;\n\n    public TaxableRegularPhone(Money amount, Duration seconds, double taxRate) {\n        super(amount, seconds);\n        this.taxRate = taxRate;\n    }\n\n    @Override\n    protected Money afterCalculated(Money fee) {\n        return fee.plus(fee.times(taxRate));\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class TaxableNightlyDiscountPhone extends NightlyDiscountPhone {\n\n    private final double taxRate;\n\n    public TaxableNightlyDiscountPhone(Money nightlyAmount, Money regularAmount, Duration seconds, double taxRate) {\n        super(nightlyAmount, regularAmount, seconds);\n        this.taxRate = taxRate;\n    }\n\n    @Override\n    protected Money afterCalculated(Money fee) {\n        return fee.plus(fee.times(taxRate));\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>부모 클래스의 이름을 제외하면 대부분의 코드가 거의 동일</li>\n</ul>\n<h3 id=\"-1124-기본-정책에-기본-요금-할인-정책-조합하기\" style=\"position:relative;\"><a href=\"#-1124-%EA%B8%B0%EB%B3%B8-%EC%A0%95%EC%B1%85%EC%97%90-%EA%B8%B0%EB%B3%B8-%EC%9A%94%EA%B8%88-%ED%95%A0%EC%9D%B8-%EC%A0%95%EC%B1%85-%EC%A1%B0%ED%95%A9%ED%95%98%EA%B8%B0\" aria-label=\" 1124 기본 정책에 기본 요금 할인 정책 조합하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 11.2.4 기본 정책에 기본 요금 할인 정책 조합하기</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class RateDiscountableRegularPhone extends RegularPhone {\n\n    private final Money discountAmount;\n\n    public RateDiscountableRegularPhone(Money amount, Duration seconds, Money discountAmount) {\n        super(amount, seconds);\n        this.discountAmount = discountAmount;\n    }\n\n    @Override\n    protected Money afterCalculated(Money fee) {\n        return fee.minus(discountAmount);\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class RateDiscountableNightlyDiscountPhone extends NightlyDiscountPhone {\n\n    private final Money discountAmount;\n\n    public RateDiscountableNightlyDiscountPhone(Money nightlyAmount, Money regularAmount, Duration seconds, Money discountAmount) {\n        super(nightlyAmount, regularAmount, seconds);\n        this.discountAmount = discountAmount;\n    }\n\n    @Override\n    protected Money afterCalculated(Money fee) {\n        return fee.minus(discountAmount);\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>또, 중복 코드가 추가되었다.</li>\n</ul>\n<h3 id=\"-1125-중복-코드의-덫에-걸리다\" style=\"position:relative;\"><a href=\"#-1125-%EC%A4%91%EB%B3%B5-%EC%BD%94%EB%93%9C%EC%9D%98-%EB%8D%AB%EC%97%90-%EA%B1%B8%EB%A6%AC%EB%8B%A4\" aria-label=\" 1125 중복 코드의 덫에 걸리다 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 11.2.5 중복 코드의 덫에 걸리다</h3>\n<p>상속을 이용한 해결 방법은 모든 가능한 조합별로 자식 클래스를 하나씩 추가하는 것이다.</p>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class TaxableAndRateDiscountableRegularPhone extends TaxableRegularPhone {\n\n    private final Money discountAmount;\n\n    public TaxableAndRateDiscountableRegularPhone(Money amount, Duration seconds, double taxRate, Money discountAmount) {\n        super(amount, seconds, taxRate);\n        this.discountAmount = discountAmount;\n    }\n\n    @Override\n    protected Money afterCalculated(Money fee) {\n        return super.afterCalculated(fee).minus(discountAmount);\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class RateDiscountableAndTaxableRegularPhone extends RateDiscountableRegularPhone {\n\n    private final double taxRate;\n\n    public RateDiscountableAndTaxableRegularPhone(Money amount, Duration seconds, Money discountAmount, double taxRate) {\n        super(amount, seconds, discountAmount);\n        this.taxRate = taxRate;\n    }\n\n    @Override\n    protected Money afterCalculated(Money fee) {\n        return super.afterCalculated(fee).plus(fee.times(taxRate));\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class TaxableAndDiscountableNightlyDiscountPhone extends TaxableNightlyDiscountPhone {\n\n    private final Money discountAmount;\n\n    public TaxableAndDiscountableNightlyDiscountPhone(Money nightlyAmount, Money regularAmount, Duration seconds, double taxRate, Money discountAmount) {\n        super(nightlyAmount, regularAmount, seconds, taxRate);\n        this.discountAmount = discountAmount;\n    }\n\n    @Override\n    protected Money afterCalculated(Money fee) {\n        return super.afterCalculated(fee).minus(discountAmount);\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class RateDiscountableAndTaxableNightlyDiscountPhone extends RateDiscountableNightlyDiscountPhone {\n\n    private final double taxRate;\n\n    public RateDiscountableAndTaxableNightlyDiscountPhone(Money nightlyAmount, Money regularAmount, Duration seconds, Money discountAmount, double taxRate) {\n        super(nightlyAmount, regularAmount, seconds, discountAmount);\n        this.taxRate = taxRate;\n    }\n\n    @Override\n    protected Money afterCalculated(Money fee) {\n        return super.afterCalculated(fee).plus(fee.times(taxRate));\n    }\n}\n</code>\n        </deckgo-highlight-code>\n<ul>\n<li><strong>클래스 폭발(class explosion)</strong> 또는 <strong>조합의 폭발(combinational explosion)</strong></li>\n<li>자식 클래스가 부모 클래스의 구현에 강하게 결합되도록 강요하는 상속의 근본적인 한계 때문에 발생</li>\n<li>기능을 추가할 때뿐만 아니라 기능을 수정할 때도 문제가 됨.</li>\n</ul>\n<h2 id=\"-113-합성-관계로-변경하기\" style=\"position:relative;\"><a href=\"#-113-%ED%95%A9%EC%84%B1-%EA%B4%80%EA%B3%84%EB%A1%9C-%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0\" aria-label=\" 113 합성 관계로 변경하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 11.3 합성 관계로 변경하기</h2>\n<p>합성을 사용하면 구현이 아닌 퍼블릭 인터페이스에 대해서만 의존할 수 있기 때문에 런타임에 객체의 관계를 변경할 수 있다.</p>\n<h3 id=\"-1131-기본-정책-합성하기\" style=\"position:relative;\"><a href=\"#-1131-%EA%B8%B0%EB%B3%B8-%EC%A0%95%EC%B1%85-%ED%95%A9%EC%84%B1%ED%95%98%EA%B8%B0\" aria-label=\" 1131 기본 정책 합성하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 11.3.1 기본 정책 합성하기</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public interface RatePolicy {\n    Money calculateFee(Phone phone);\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public abstract class BasicRatePolicy implements RatePolicy{\n\n    @Override\n    public Money calculateFee(Phone phone) {\n        Money result = Money.ZERO;\n\n        for (Call call : phone.getCalls()) {\n            result.plus(calculateCallFee(call));\n        }\n\n        return result;\n    }\n\n    protected abstract Money calculateCallFee(Call call);\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic class RegularPolicy extends BasicRatePolicy {\n\n    private final Money amount;\n    private final Duration seconds;\n\n    @Override\n    protected Money calculateCallFee(Call call) {\n        return amount.times((double) call.getDuration().getSeconds() / seconds.getSeconds());\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic class NightlyDiscountPolicy extends BasicRatePolicy {\n\n    private static final int LATE_NIGHT_HOUR = 22;\n\n    private final Money nightlyAmount;\n    private final Money regularAmount;\n    private final Duration seconds;\n\n    @Override\n    protected Money calculateCallFee(Call call) {\n        if (call.getFrom().getHour() &gt;= LATE_NIGHT_HOUR) {\n            return nightlyAmount.times((double) call.getDuration().getSeconds() / seconds.getSeconds());\n        }\n        return regularAmount.times((double) call.getDuration().getSeconds() / seconds.getSeconds());\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic class Phone {\n\n    private final RatePolicy ratePolicy;\n\n    @Getter\n    private List&lt;Call&gt; calls = new ArrayList&lt;&gt;();\n\n    public Money calculateFee() {\n        return ratePolicy.calculateFee(this);\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>다양한 종류의 객체와 협력하기 위해 합성 관계를 사용하는 경우에는 합성하는 객체의 타입을 인터페이스나 추상 클래스로 선언하고 의존성 주입을 사용해 런타임에 필요한 객체를 설정할 수 있도록 구현하는 것이 일반적이다.</li>\n</ul>\n<h3 id=\"-1132-부가-정책-적용하기\" style=\"position:relative;\"><a href=\"#-1132-%EB%B6%80%EA%B0%80-%EC%A0%95%EC%B1%85-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0\" aria-label=\" 1132 부가 정책 적용하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 11.3.2 부가 정책 적용하기</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic abstract class AdditionalRatePolicy implements RatePolicy {\n\n    private final RatePolicy next;\n\n    @Override\n    public Money calculateFee(Phone phone) {\n        Money fee = next.calculateFee(phone);\n        return afterCalculated(fee);\n    }\n\n    protected abstract Money afterCalculated(Money fee);\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class TaxablePolicy extends AdditionalRatePolicy {\n    \n    private final double taxRatio;\n\n    public TaxablePolicy(RatePolicy next, double taxRatio) {\n        super(next);\n        this.taxRatio = taxRatio;\n    }\n\n    @Override\n    protected Money afterCalculated(Money fee) {\n        return fee.plus(fee.times(taxRatio));\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class RateDiscountablePolicy extends AdditionalRatePolicy {\n\n    private final Money discountAmount;\n\n    public RateDiscountablePolicy(RatePolicy next, Money discountAmount) {\n        super(next);\n        this.discountAmount = discountAmount;\n    }\n\n    @Override\n    protected Money afterCalculated(Money fee) {\n        return fee.minus(discountAmount);\n    }\n}</code>\n        </deckgo-highlight-code>\n<h3 id=\"-1133-기본-정책과-부가-정책-합성하기\" style=\"position:relative;\"><a href=\"#-1133-%EA%B8%B0%EB%B3%B8-%EC%A0%95%EC%B1%85%EA%B3%BC-%EB%B6%80%EA%B0%80-%EC%A0%95%EC%B1%85-%ED%95%A9%EC%84%B1%ED%95%98%EA%B8%B0\" aria-label=\" 1133 기본 정책과 부가 정책 합성하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 11.3.3 기본 정책과 부가 정책 합성하기</h3>\n<p><code>Phone phone = new Phone(new taxablePolicy(0.05, new RegularPolicy(...)))</code></p>\n<ul>\n<li>객체를 조합하고 사용하는 방식이 상속을 사용한 방식보다 더 예측 가능하고 일관성 있다.</li>\n</ul>\n<h3 id=\"-1134-새로운-정책-추가하기\" style=\"position:relative;\"><a href=\"#-1134-%EC%83%88%EB%A1%9C%EC%9A%B4-%EC%A0%95%EC%B1%85-%EC%B6%94%EA%B0%80%ED%95%98%EA%B8%B0\" aria-label=\" 1134 새로운 정책 추가하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 11.3.4 새로운 정책 추가하기</h3>\n<ul>\n<li>오직 하나의 클래스만 추가하고 런타임에 필요한 정책들을 조합해서 원하는 기능을 얻을 수 있다.</li>\n<li>요구사항을 변경할 때 오직 하나의 클래스만 수정해도 된다.\n<ul>\n<li>변경 후의 설계는 단일 책임 원칙을 준수하고 있다.</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-1135-객체-합성이-클래스-상속보다-더-좋은-방법이다\" style=\"position:relative;\"><a href=\"#-1135-%EA%B0%9D%EC%B2%B4-%ED%95%A9%EC%84%B1%EC%9D%B4-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%83%81%EC%86%8D%EB%B3%B4%EB%8B%A4-%EB%8D%94-%EC%A2%8B%EC%9D%80-%EB%B0%A9%EB%B2%95%EC%9D%B4%EB%8B%A4\" aria-label=\" 1135 객체 합성이 클래스 상속보다 더 좋은 방법이다 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 11.3.5 객체 합성이 클래스 상속보다 더 좋은 방법이다</h3>\n<ul>\n<li>상속은 부모 클래스의 세부적인 구현에 자식 클래스를 강하게 결합시키기 때문에 코드의 진화를 방해한다.</li>\n<li>상속이 구현을 재사용하는 데 비해 합성은 객체의 인터페이스를 재사용한다.</li>\n<li>상속의 종류: 구현 상속 / 인터페이스 상속\n<ul>\n<li>이번 장에서 살펴본 상속의 단점은 구현 상속</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"-114-믹스인\" style=\"position:relative;\"><a href=\"#-114-%EB%AF%B9%EC%8A%A4%EC%9D%B8\" aria-label=\" 114 믹스인 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 11.4 믹스인</h2>\n<ul>\n<li>객체를 생성할 때 코드 일부를 클래스 안에 섞어 넣어 재사용하는 기법을 가리키는 용어</li>\n<li>코드를 다른 코드 안에 섞어 넣기 위한 방법</li>\n<li>상속이 클래스와 클래스 사이의 관계를 고정시키는 데 비해 믹스인은 유연하게 관계를 재구성할 수 있다.</li>\n<li><a href=\"https://bottleh.netlify.app/backend/effective-java/4%EC%9E%A5_%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80_%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4/#%EC%95%84%EC%9D%B4%ED%85%9C20-%EC%B6%94%EC%83%81-%ED%81%B4%EB%9E%98%EC%8A%A4%EB%B3%B4%EB%8B%A4%EB%8A%94-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4%EB%A5%BC-%EC%9A%B0%EC%84%A0%ED%95%98%EB%9D%BC\">이펙티브 자바 아이템20</a></li>\n<li>java에서 인터페이스는 믹스인 정의에 안성맞춤이지만, 추상 클래스는 믹스인을 정의할 수 없다.</li>\n</ul>\n<h2 id=\"-1141-쌓을-수-있는-변경\" style=\"position:relative;\"><a href=\"#-1141-%EC%8C%93%EC%9D%84-%EC%88%98-%EC%9E%88%EB%8A%94-%EB%B3%80%EA%B2%BD\" aria-label=\" 1141 쌓을 수 있는 변경 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 11.4.1 쌓을 수 있는 변경</h2>\n<ul>\n<li>믹스인은 대상 클래스의 자식 클래스처럼 사용될 용도로 만들어지는 것</li>\n<li>믹스인을 추상 서브클래스(abstract subclass)라고 부르기도 한다.</li>\n<li>쌓을 수 있는 변경: 믹스인을 사용하면 특정한 클래스에 대한 변경 또는 확장을 독립적으로 구현한 후 필요한 시점에 차례대로 추가할 수 있다.</li>\n</ul>","excerpt":"상속 부모 클래스와 자식 클래스 사이의 의존성은 컴파일타임에 해결 is-a 관계 클래스 사이의 정적 관계 합성 부모 클래스와 자식 클래스 사이의 의존성은 런타임에 해결 has-a 관계 객체 사이의 동적 관계 코드 재사용을 위해서는 객체 합성이 클래스 상속보다 더 좋은 방법이다. 📖 11.1 상속을 합성으로 변경하기 상속을 남용할 때 직면하는 세 가지 문제 불필요한 인터페이스 상속 문제 메서드 오버라이딩의 오작용 문제 부모 클래스와 자식 클래스의 동시 수정 문제 🔖 11.1.…","fields":{"slug":"/backend/object/chapter11/합성과_유연한_설계/"},"frontmatter":{"title":"Object - 11장 합성과 유연한 설계","thumbnail":{"childImageSharp":{"fluid":{"src":"/static/dd0e1990925e942697544e2bdcd9332e/9b73b/object.png"}}},"draft":false,"category":"Back-End","tags":["java"],"date":"November 05, 2023"}},"previous":{"id":"5e0a5e6c-4129-58ae-af88-f36029bc2dcf","html":"<p>상속의 용도</p>\n<ol>\n<li>타입 계층 구현</li>\n<li>코드 재사용</li>\n</ol>\n<h2 id=\"-131-타입\" style=\"position:relative;\"><a href=\"#-131-%ED%83%80%EC%9E%85\" aria-label=\" 131 타입 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 13.1 타입</h2>\n<p>프로그래밍 언어 관점에서의 타입과 개념 관점에서의 타입</p>\n<h3 id=\"-1311-개념-관점의-타입\" style=\"position:relative;\"><a href=\"#-1311-%EA%B0%9C%EB%85%90-%EA%B4%80%EC%A0%90%EC%9D%98-%ED%83%80%EC%9E%85\" aria-label=\" 1311 개념 관점의 타입 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 13.1.1 개념 관점의 타입</h3>\n<p>개념 관점에서 타입이란 우리가 인지하는 세상의 사물의 종류를 의미한다.</p>\n<p>어떤 대상이 타입으로 분류될 때 그 대상을 타입의 인스턴스(instance)**라고 부른다.</p>\n<ul>\n<li>타입의 인스턴스를 <strong>객체</strong>라고 부름.</li>\n<li>심볼(symbol): 타입에 이름을 붙인 것</li>\n<li>내연(intension): 타입의 정의로서 타입에 속하는 객체들이 가지는 공통적인 속성이나 행동</li>\n<li>외연(extension): 타입에 속하는 객체들의 집합</li>\n</ul>\n<h3 id=\"-1312-프로그래밍-언어-관점의-타입\" style=\"position:relative;\"><a href=\"#-1312-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EC%96%B8%EC%96%B4-%EA%B4%80%EC%A0%90%EC%9D%98-%ED%83%80%EC%9E%85\" aria-label=\" 1312 프로그래밍 언어 관점의 타입 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 13.1.2 프로그래밍 언어 관점의 타입</h3>\n<p>프로그래밍 언어 관점에서 타입은 연속적인 비트에 의미와 제약을 부여하기 위해 사용하며 두 가지 목적이 있다.</p>\n<ol>\n<li>타입에 수행될 수 있는 유효한 오퍼레이션의 집합을 정의</li>\n<li>타입에 수행되는 오퍼레이션에 대해 미리 약속된 문맥을 제공</li>\n</ol>\n<p>타입은 적용 가능한 오퍼레이션의 종류와 의미를 정의함으로써 코드의 의미를 명확하게 전달하고 개발자의 실수를 방지하기 위해 사용</p>\n<h3 id=\"-1313-객체지향-패러다임-관점의-타입\" style=\"position:relative;\"><a href=\"#-1313-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%ED%8C%A8%EB%9F%AC%EB%8B%A4%EC%9E%84-%EA%B4%80%EC%A0%90%EC%9D%98-%ED%83%80%EC%9E%85\" aria-label=\" 1313 객체지향 패러다임 관점의 타입 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 13.1.3 객체지향 패러다임 관점의 타입</h3>\n<ul>\n<li>개념 관점에서 타입이란 공통의 특징을 공유하는 대상들의 분류다.</li>\n<li>프로그래밍 언어 관점에서 타입이란 동일한 오퍼레이션을 적용할 수 있는 인스턴스들의 집합</li>\n</ul>\n<p>객체의 타입이란 객체가 수신할 수 있는 메시지의 종류를 정의하는 것</p>\n<ul>\n<li>객체지향 프로그래밍에서 타입을 정의하는 것은 객체의 <strong>퍼블릭 인터페이스</strong>를 정의하는 것과 동일</li>\n<li>동일한 퍼블릭 인터페이스를 제공하는 객체들은 동일한 타입으로 분류된다.</li>\n<li>객체의 타입을 결정하는 것은 내부의 속성이 아니라 객체가 외부에 제공하는 행동이다.</li>\n</ul>\n<h2 id=\"-132-타입-계층\" style=\"position:relative;\"><a href=\"#-132-%ED%83%80%EC%9E%85-%EA%B3%84%EC%B8%B5\" aria-label=\" 132 타입 계층 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 13.2 타입 계층</h2>\n<h3 id=\"-1321-타입-사이의-포함관계\" style=\"position:relative;\"><a href=\"#-1321-%ED%83%80%EC%9E%85-%EC%82%AC%EC%9D%B4%EC%9D%98-%ED%8F%AC%ED%95%A8%EA%B4%80%EA%B3%84\" aria-label=\" 1321 타입 사이의 포함관계 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 13.2.1 타입 사이의 포함관계</h3>\n<p>타입이 다른 타입에 포함될 수 있기 때문에 동일한 인스턴스가 하나 이상의 타입으로 분류되는 것도 가능</p>\n<p>타입 계층을 구성하는 두 타입 관계에서 더 일반적인 타입을 **슈퍼타입(supertype)**이라고 부르고 더 특수한 타입을 **서브타입(subtype)**이라고 부른다.</p>\n<p>내연 관점</p>\n<ul>\n<li>일반화: 어떤 타입의 정의를 좀 더 보편적이고 추상적으로 만드는 과정을 의미</li>\n<li>특수화: 어떤 타입의 정의를 좀 더 구체적이고 문맥 종속적으로 만드는 과정을 의미</li>\n</ul>\n<p>외연 관점</p>\n<ul>\n<li>슈퍼셋(superset): 일반적인 타입의 인스턴스 집합은 특수한 타입의 인스턴스 집합을 포함</li>\n<li>서브셋(subset): 특수한 타입의 인스턴스 집합은 일반적인 타입의 인스턴스 집합에 포함</li>\n</ul>\n<h3 id=\"-1322-객체지향-프로그래밍과-타입-계층\" style=\"position:relative;\"><a href=\"#-1322-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EA%B3%BC-%ED%83%80%EC%9E%85-%EA%B3%84%EC%B8%B5\" aria-label=\" 1322 객체지향 프로그래밍과 타입 계층 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 13.2.2 객체지향 프로그래밍과 타입 계층</h3>\n<ul>\n<li>슈퍼타입이란 서브타입이 정의한 퍼블릭 인터페이스를 일반화시켜 상대적으로 범용적이고 넓은 의미로 정의</li>\n<li>서브타입이란 슈퍼타입이 정의한 퍼블릭 인터페이스를 특수화시켜 상대적으로 구체적이고 좁은 의미로 정의</li>\n</ul>\n<p>서브타입의 인스턴스는 슈퍼타입의 인스턴스로 간주될 수 있다.</p>\n<h2 id=\"-133-서브클래싱과-서브타이핑\" style=\"position:relative;\"><a href=\"#-133-%EC%84%9C%EB%B8%8C%ED%81%B4%EB%9E%98%EC%8B%B1%EA%B3%BC-%EC%84%9C%EB%B8%8C%ED%83%80%EC%9D%B4%ED%95%91\" aria-label=\" 133 서브클래싱과 서브타이핑 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 13.3 서브클래싱과 서브타이핑</h2>\n<h3 id=\"-1331-언제-상속을-사용해야-하는가\" style=\"position:relative;\"><a href=\"#-1331-%EC%96%B8%EC%A0%9C-%EC%83%81%EC%86%8D%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%B4%EC%95%BC-%ED%95%98%EB%8A%94%EA%B0%80\" aria-label=\" 1331 언제 상속을 사용해야 하는가 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 13.3.1 언제 상속을 사용해야 하는가?</h3>\n<p>아래 두 질문에 모두 '예'라고 답할 수 있는 경우에만 상속을 사용</p>\n<ol>\n<li>상속 관계가 is-a 관계를 모델링하는가?</li>\n<li>클라이언트 입장에서 부모 클래스의 타입으로 자식 클래스를 사용해도 무방한가?</li>\n</ol>\n<h3 id=\"-1332-is-a-관계\" style=\"position:relative;\"><a href=\"#-1332-is-a-%EA%B4%80%EA%B3%84\" aria-label=\" 1332 is a 관계 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 13.3.2 is-a 관계</h3>\n<p>어떤 타입 S가 다른 타입 T의 일종이라면 당연히 <code>타입 S는 타입 T다</code>라고 답할 수 있어야 한다.</p>\n<p>타입 계층의 의미는 행동이라는 문맥에 따라 달라질 수 있다.</p>\n<ul>\n<li>ex. 펭귄은 새다, 새는 날 수 있다.</li>\n<li>행동호환성이 더 중요</li>\n</ul>\n<h3 id=\"-1333-행동-호환성\" style=\"position:relative;\"><a href=\"#-1333-%ED%96%89%EB%8F%99-%ED%98%B8%ED%99%98%EC%84%B1\" aria-label=\" 1333 행동 호환성 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 13.3.3 행동 호환성</h3>\n<p>타입의 이름 사이에 개념적으로 어떤 연관성이 있다고 하더라도 행동에 연관성이 없다면 is-a 관계를 사용하지 말아야 한다.</p>\n<ul>\n<li>행동의 호환 여부를 판단하는 기준은 <strong>클라이언트의 관점</strong>이다.</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public void flyBird(Bird bird) {\n\n  // 인자로 전달된 모든 bird들은 날 수 있어야 한다.\n  bird.fly();\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class Penguin extends Bird {\n\n  ...\n\n  @Override\n  public void fly() {}\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>모든 bird가 날 수 있다는 클라이언트의 기대를 만족시키지 못한다.</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class Penguin extends Bird {\n\n  ...\n\n  @Override\n  public void fly() {\n      throw new UnsupportedOperationException();\n  }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>UnsupportedOperationException</code> 예외가 던져질 것이라고는 기대하지 않았을 것이다.</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public void flyBird(Bird bird) {\n\n  // 인자로 전달된 모든 birtd가 Penguin의 인스턴스가 아닐 경우에만 fly() 메시지를 전송한다.\n  if (!(bird instanceof Penguin)) {\n      bird.fly();\n  }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>Penguin 이외에 날 수 없는 또 다른 새가 상속 계층에 추가 될 수도 있어 결합도를 높인다.</li>\n<li>개방-폐쇄 원칙을 위반</li>\n</ul>\n<h3 id=\"-1334-클라이언트의-기대에-따라-계층-분리하기\" style=\"position:relative;\"><a href=\"#-1334-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8%EC%9D%98-%EA%B8%B0%EB%8C%80%EC%97%90-%EB%94%B0%EB%9D%BC-%EA%B3%84%EC%B8%B5-%EB%B6%84%EB%A6%AC%ED%95%98%EA%B8%B0\" aria-label=\" 1334 클라이언트의 기대에 따라 계층 분리하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 13.3.4 클라이언트의 기대에 따라 계층 분리하기</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class Bird {\n  ...\n}\n\npublic class FlyingBird extends Bird {\n  \n  public void fly() { ... }\n  \n  ...\n}\n\npublic class Penguin extends Bird {\n  ...\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>모든 클래스들이 행동호환성을 만족시킨다.</li>\n</ul>\n<p>이 문제를 해결하는 다른 방법은 클라이언트에 따라 인터페이스를 분리하는 것이지만 더 좋은 방법은 합성을 사용하는 것이다.</p>\n<blockquote>\n<p>자연어에 현혹되지 말고 요구사항 속에서 클라이언트가 기대하는 행동에 집중</p>\n</blockquote>\n<h3 id=\"-1335-서브클래싱과-서브타이핑\" style=\"position:relative;\"><a href=\"#-1335-%EC%84%9C%EB%B8%8C%ED%81%B4%EB%9E%98%EC%8B%B1%EA%B3%BC-%EC%84%9C%EB%B8%8C%ED%83%80%EC%9D%B4%ED%95%91\" aria-label=\" 1335 서브클래싱과 서브타이핑 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 13.3.5 서브클래싱과 서브타이핑</h3>\n<p>상속을 사용하는 두 가지 목적</p>\n<ol>\n<li>\n<p>**서브클래싱(subclassing)</p>\n<ul>\n<li>다른 클래스의 코드를 재사용할 목적으로 상속을 사용하는 경우</li>\n<li>자식 클래스와 부모 클래스의 행동이 호환되지 않기 때문에 자식 클래스의 인스턴스가 부모 클래스의 인스턴스를 대체할 수 없다.</li>\n<li>구현상속(implementation inheritance) 또는 클래스 상속(class inheritance)**이라고 부른다.</li>\n</ul>\n</li>\n<li>\n<p>**서브 타이핑(subtyping)</p>\n<ul>\n<li>타입 계층을 구성하기 위해 상속을 사용하는 경우</li>\n<li>서브타이핑에서는 자식 클래스와 부모 클래스의 행동이 호환되기 때문에 자식 클래스의 인스턴스가 부모 클래스의 인스턴스를 대체할 수 있다.</li>\n<li>이때 부모 클래스는 자식클래스의 슈퍼타입이 되고 자식 클래스는 부모 클래스의 서브타입이 된다.</li>\n<li>인터페이스 상속(interface inheritance)이라고 부른다.</li>\n</ul>\n</li>\n</ol>\n<p>어떤 타입이 다른 타입의 서브타입이 되기 위해서는 <strong>행동 호환성</strong>을 만족시켜야 한다. 자식 클래스와 부모 클래스 사이의 행동 호환성은 부모 클래스에 대한 자식 클래스의 **대체 가능성(substitutability)**을 포함한다.</p>\n<h2 id=\"-134-리스코프-치환-원칙\" style=\"position:relative;\"><a href=\"#-134-%EB%A6%AC%EC%8A%A4%EC%BD%94%ED%94%84-%EC%B9%98%ED%99%98-%EC%9B%90%EC%B9%99\" aria-label=\" 134 리스코프 치환 원칙 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 13.4 리스코프 치환 원칙</h2>\n<blockquote>\n<p>서브타입은 그것의 기반 타입에 대해 대체 가능해야 한다.</p>\n</blockquote>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@AllArgsConstructor\npublic class Rectangle {\n    \n    private final int x;\n    \n    private final int y;\n    \n    @Getter\n    @Setter\n    private int width;\n    \n    @Getter\n    @Setter\n    private int height;\n    \n    public int getArea() {\n        return width * height;\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class Square extends Rectangle {\n\n    public Square(int x, int y, int width, int height) {\n        super(x, y, width, height);\n    }\n\n    @Override\n    public void setWidth(int width) {\n        super.setWidth(width);\n        super.setHeight(width);\n    }\n\n    @Override\n    public void setHeight(int height) {\n        super.setWidth(height);\n        super.setHeight(height);\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>Square의 너비와 높이는 항상 더 나중에 설정된 height의 값으로 설정된다.</li>\n<li>Square는 Rectangle의 구현을 재사용하고 있을 뿐이다. 즉, 서브클래싱 관계다.</li>\n</ul>\n<h3 id=\"-1341-클라이언트와-대체-가능성\" style=\"position:relative;\"><a href=\"#-1341-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8%EC%99%80-%EB%8C%80%EC%B2%B4-%EA%B0%80%EB%8A%A5%EC%84%B1\" aria-label=\" 1341 클라이언트와 대체 가능성 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 13.4.1 클라이언트와 대체 가능성</h3>\n<blockquote>\n<p>클라이언트와 격리한 채로 본 모델은 의미 있게 검증하는 것이 불가능하다.</p>\n</blockquote>\n<ul>\n<li>리스코프 치환 원칙은 상속 관계에 있는 두 클래스 사이의 관계를 클라이언트와 떨어트려 놓고 판단하지 말라고 속삭인다.</li>\n</ul>\n<h3 id=\"-1342-is-a-관계-다시-살펴보기\" style=\"position:relative;\"><a href=\"#-1342-is-a-%EA%B4%80%EA%B3%84-%EB%8B%A4%EC%8B%9C-%EC%82%B4%ED%8E%B4%EB%B3%B4%EA%B8%B0\" aria-label=\" 1342 is a 관계 다시 살펴보기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 13.4.2 is-a 관계 다시 살펴보기</h3>\n<p>클라이언트 관점에서 자식 클래스의 행동이 부모 클래스의 행동과 호환되지 않고 그로 인해 대체가 불가능하다면 어휘적으로 is-a라고 말할 수 있다고 하더라도 그 관계를 is-a 관계라고 할 수 없다.</p>\n<ul>\n<li>상속이 서브타이핑을 위해 사용될 경우에만 is-a 관계</li>\n</ul>\n<h3 id=\"-1343-리스코프-치환-원칙은-유연한-설계의-기반이다\" style=\"position:relative;\"><a href=\"#-1343-%EB%A6%AC%EC%8A%A4%EC%BD%94%ED%94%84-%EC%B9%98%ED%99%98-%EC%9B%90%EC%B9%99%EC%9D%80-%EC%9C%A0%EC%97%B0%ED%95%9C-%EC%84%A4%EA%B3%84%EC%9D%98-%EA%B8%B0%EB%B0%98%EC%9D%B4%EB%8B%A4\" aria-label=\" 1343 리스코프 치환 원칙은 유연한 설계의 기반이다 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 13.4.3 리스코프 치환 원칙은 유연한 설계의 기반이다</h3>\n<p>리스코프 치환 원칙은 개방-폐쇄 원칙을 만족하는 설계를 위한 전제 조건이다.</p>\n<ul>\n<li>자식 클래스가 클라이언트의 관점에서 부모 클래스를 대체할 수 있다면 기능 확장을 위해 자식 클래스를 추가하더라도 코드를 수정할 필요가 없어진다.</li>\n</ul>\n<h3 id=\"-1344-타입-계층과-리스코프-치환-원칙\" style=\"position:relative;\"><a href=\"#-1344-%ED%83%80%EC%9E%85-%EA%B3%84%EC%B8%B5%EA%B3%BC-%EB%A6%AC%EC%8A%A4%EC%BD%94%ED%94%84-%EC%B9%98%ED%99%98-%EC%9B%90%EC%B9%99\" aria-label=\" 1344 타입 계층과 리스코프 치환 원칙 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 13.4.4 타입 계층과 리스코프 치환 원칙</h3>\n<p>클래스 상속은 타입 계층을 구현할 수 있는 다양한 방법 중 하나일 뿐이다.</p>\n<ul>\n<li>구현 방법과 무관하게 클라이언트의 관점에서 슈퍼타입에 대해 기대하는 모든 것이 서브타입에게도 적용돼야 한다.</li>\n</ul>\n<h2 id=\"-135-계약에-의한-설계와-서브타이핑\" style=\"position:relative;\"><a href=\"#-135-%EA%B3%84%EC%95%BD%EC%97%90-%EC%9D%98%ED%95%9C-%EC%84%A4%EA%B3%84%EC%99%80-%EC%84%9C%EB%B8%8C%ED%83%80%EC%9D%B4%ED%95%91\" aria-label=\" 135 계약에 의한 설계와 서브타이핑 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 13.5 계약에 의한 설계와 서브타이핑</h2>\n<p>계약에 의한 설계(Design By Contract, DBC)</p>\n<ul>\n<li>클라이언트와 서버 사이의 협력을 의무와 이익으로 구성된 계약의 관점에서 표현하는 것</li>\n<li>사전조건: 클라이언트가 정상적으로 메서드를 실행하기 위해 만족시켜야 하는 조건</li>\n<li>사후조건: 메서드가 실행된 후에 서버가 클라이언트에게 보장해야 하는 조건</li>\n<li>클래스 불변식: 메서드 실행 전과 실행 후에 인스턴스가 만족시켜야 하는 것</li>\n</ul>\n<blockquote>\n<p>서브타입이 리스코프 치환 원칙을 만족시키기 위해서는 클라이언트와 슈퍼타입 간에 체결된 '계약'을 준수해야 한다.</p>\n</blockquote>\n<h3 id=\"-1351-서브타입과-계약\" style=\"position:relative;\"><a href=\"#-1351-%EC%84%9C%EB%B8%8C%ED%83%80%EC%9E%85%EA%B3%BC-%EA%B3%84%EC%95%BD\" aria-label=\" 1351 서브타입과 계약 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 13.5.1 서브타입과 계약</h3>\n<p>어떤 타입이 슈퍼타입에서 정의한 사전조건보다 더 약한 사전조건을 정의하고 있다면 그 타입은 서브타입이 될 수 있지만 더 강한 사전조건을 정의한다면 서브타입이 될 수 없다.</p>\n<p>계약에 의한 설계는 클라이언트 관점에서의 대체 가능성을 계약으로 설명할 수 있다는 사실을 잘 보여준다.</p>","excerpt":"상속의 용도 타입 계층 구현 코드 재사용 📖 13.1 타입 프로그래밍 언어 관점에서의 타입과 개념 관점에서의 타입 🔖 13.1.1 개념 관점의 타입 개념 관점에서 타입이란 우리가 인지하는 세상의 사물의 종류를 의미한다. 어떤 대상이 타입으로 분류될 때 그 대상을 타입의 인스턴스(instance)**라고 부른다. 타입의 인스턴스를 객체라고 부름. 심볼(symbol): 타입에 이름을 붙인 것 내연(intension…","fields":{"slug":"/backend/object/chapter13/서브클래싱과_서브타이핑/"},"frontmatter":{"title":"Object - 13장 서브클래싱과 서브타이핑","thumbnail":{"childImageSharp":{"fluid":{"src":"/static/dd0e1990925e942697544e2bdcd9332e/9b73b/object.png"}}},"draft":false,"category":"Back-End","tags":["java"],"date":"November 19, 2023"}},"node":{"id":"1020f854-93fe-54be-b1d8-bb9f82d9c3a4","html":"<p>상속의 목적이 코드 재사용이라면 사용하지 말아야 한다. 다형성이 런타임에 메시지를 처리하기에 적합한 메서드를 동적으로 탐색하는 과정을 통해 구현되며, 상속이 이런 메서드를 찾기 위한 일종의 탐색 경로를 클래스 계층의 형태로 구현된다.</p>\n<h2 id=\"-121-다형성\" style=\"position:relative;\"><a href=\"#-121-%EB%8B%A4%ED%98%95%EC%84%B1\" aria-label=\" 121 다형성 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 12.1 다형성</h2>\n<ul>\n<li>많은 형태를 가질 수 있는 능력</li>\n<li>Universal 다형성\n<ul>\n<li>Parametric 다형성\n<ul>\n<li>클래스의 인스턴스 변수나 메서드의 매개변수 타입을 임의의 타입으로 선언한 후 사용하는 시점에 구체적인 타입으로 지정하는 방식</li>\n<li>제네릭 프로그래밍</li>\n</ul>\n</li>\n<li>Inclustion 다형성\n<ul>\n<li>메시지가 동일하더라도 수신한 객체의 타입에 따라 실제로 수행되는 행동이 달라지는 능력</li>\n<li>Subtype 다형성</li>\n<li>가장 널리 알려진 형태</li>\n</ul>\n</li>\n</ul>\n</li>\n<li>Ad Hoc 다형성\n<ul>\n<li>Overloading 다형성\n<ul>\n<li>하나의 클래스 안에 동일한 이름의 메서드가 존재하는 경우</li>\n</ul>\n</li>\n<li>Coercion 다형성\n<ul>\n<li>언어가 지원하는 자동적인 타입 변환이나 사용자가 직접 구현한 타입 변환을 이용해 동일한 연산자를 다양한 타입에 사용할 수 있는 방식</li>\n<li>java의 <code>+</code> 연산자</li>\n</ul>\n</li>\n</ul>\n</li>\n<li>상속의 일차적인 목적은 서브타입의 구현이다.</li>\n</ul>\n<h2 id=\"-122-상속의-양면성\" style=\"position:relative;\"><a href=\"#-122-%EC%83%81%EC%86%8D%EC%9D%98-%EC%96%91%EB%A9%B4%EC%84%B1\" aria-label=\" 122 상속의 양면성 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 12.2 상속의 양면성</h2>\n<p>객체지향 프로그램을 작성하기 위해서는 항상 데이터와 행동이라는 두 가지 관점을 함께 고려해야 한다.</p>\n<ul>\n<li>데이터 관점의 상속\n<ul>\n<li>부모 클래스에서 정의한 모든 데이터를 자식 클래스의 인스턴스에 자동으로 포함</li>\n</ul>\n</li>\n<li>행동 관점의 상속\n<ul>\n<li>부모 클래스에서 정의한 일부 메서드 역시 자동으로 자식 클래스에 포함</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-1221-상속을-사용한-강의-평가\" style=\"position:relative;\"><a href=\"#-1221-%EC%83%81%EC%86%8D%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%9C-%EA%B0%95%EC%9D%98-%ED%8F%89%EA%B0%80\" aria-label=\" 1221 상속을 사용한 강의 평가 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 12.2.1 상속을 사용한 강의 평가</h3>\n<h4 id=\"-lecture-클래스-살펴보기\" style=\"position:relative;\"><a href=\"#-lecture-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%82%B4%ED%8E%B4%EB%B3%B4%EA%B8%B0\" aria-label=\" lecture 클래스 살펴보기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🎈 Lecture 클래스 살펴보기</h4>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic class Lecture {\n\n    /**\n     * 이수 여부를 판단할 기준 점수\n     */\n    private final int pass;\n\n    /**\n     * 과목명\n     */\n    private final String title;\n\n    /**\n     * 학생들의 성적\n     */\n    private final List&lt;Integer&gt; scores;\n\n    public double average() {\n        return scores.stream()\n                .mapToInt(Integer::intValue)\n                .average().orElse(0);\n    }\n\n    public List&lt;Integer&gt; getScores() {\n        return Collections.unmodifiableList(scores);\n    }\n\n    public String evaluate() {\n        return String.format(&quot;Pass:%d Fail:%d&quot;, passCount(), failCount());\n    }\n\n    private long passCount() {\n        return scores.stream().filter(score -&gt; score &gt;= pass).count();\n    }\n\n    private long failCount() {\n        return scores.size() - passCount();\n    }\n}</code>\n        </deckgo-highlight-code>\n<h4 id=\"-상속을-이용해-lecture-클래스-재사용하기\" style=\"position:relative;\"><a href=\"#-%EC%83%81%EC%86%8D%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%B4-lecture-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%9E%AC%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0\" aria-label=\" 상속을 이용해 lecture 클래스 재사용하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🎈 상속을 이용해 Lecture 클래스 재사용하기</h4>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic class Grade {\n\n    /**\n     * 등급 이름\n     */\n    @Getter\n    private final String name;\n\n    /**\n     * 최대 성적, 최소 성적\n     */\n    private final int upper, lower;\n\n    public boolean isName(String name) {\n        return this.name.equals(name);\n    }\n\n    public boolean include(int score) {\n        return score &gt;= lower &amp;&amp; score &lt;= upper;\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class GradeLecture extends Lecture {\n\n    private final List&lt;Grade&gt; grades;\n\n    public GradeLecture(int pass, String title, List&lt;Integer&gt; scores, List&lt;Grade&gt; grades) {\n        super(pass, title, scores);\n        this.grades = grades;\n    }\n\n    @Override\n    public String evaluate() {\n        return super.evaluate() + &quot;, &quot; + gradesStatistics();\n    }\n\n    private String gradesStatistics() {\n        return grades.stream()\n                .map(this::format)\n                .collect(joining(&quot; &quot;));\n    }\n\n    private String format(Grade grade) {\n        return String.format(&quot;%s:%d&quot;, grade.getName(), gradeCount(grade));\n    }\n\n    private long gradeCount(Grade grade) {\n        return getScores().stream()\n                .filter(grade::include)\n                .count();\n    }\n\n        public double average(String gradeName) {\n        return grades.stream()\n                .filter(each -&gt; each.isName(gradeName))\n                .findFirst()\n                .map(this::gradeAverage)\n                .orElse(0d);\n    }\n    \n    private double gradeAverage(Grade grade) {\n        return getScores().stream()\n                .filter(grade::include)\n                .mapToInt(Integer::intValue)\n                .average()\n                .orElse(0);\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>부모 클래스와 자식 클래스에 동일한 시그니처를 가진 메서드가 존재할 경우 자식 클래스의 메서드 우선순위가 더 높다.\n<ul>\n<li>메서드 오버라이딩</li>\n</ul>\n</li>\n<li>자식 클래스에 부모 클래스에는 없던 새로운 메서드를 추가하는 것도 가능</li>\n<li>부모 클래스에서 정의한 메서드와 이름은 동일하지만 시그니처는 다른 메서드를 자식 클래스에 추가\n<ul>\n<li>메서드 오버로딩</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-1222-데이터-관점의-상속\" style=\"position:relative;\"><a href=\"#-1222-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EA%B4%80%EC%A0%90%EC%9D%98-%EC%83%81%EC%86%8D\" aria-label=\" 1222 데이터 관점의 상속 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 12.2.2 데이터 관점의 상속</h3>\n<p>데이터 관점에서 상속은 자식 클래스의 인스턴스 안에 부모 클래스의 인스턴스를 포함하는 것으로 볼 수 있다.</p>\n<ul>\n<li>자식 클래스의 인스턴스는 자동으로 부모 클래스에서 정의한 모든 인스턴스 변수를 내부에 포함하게 되는 것이다.</li>\n</ul>\n<h3 id=\"-1223-행동-관점의-상속\" style=\"position:relative;\"><a href=\"#-1223-%ED%96%89%EB%8F%99-%EA%B4%80%EC%A0%90%EC%9D%98-%EC%83%81%EC%86%8D\" aria-label=\" 1223 행동 관점의 상속 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 12.2.3 행동 관점의 상속</h3>\n<p>부모 클래스의 모든 퍼블릭 메서드는 자식 클래스의 퍼블릭 인터페이스에 포함된다.</p>\n<ul>\n<li>외부의 객체가 부모 클래스의 인스턴스에게 전송할 수 있는 모든 메시지는 자식 클래스의 인스턴스에게도 전송할 수 있다.</li>\n<li>런타임에 시스템이 자식 클래스에 정의되지 않은 메서드가 있을 경우 이 메서드를 부모 클래스 안에서 탐색하기 때문❗️</li>\n</ul>\n<h2 id=\"-123-업캐스팅과-동적-바인딩\" style=\"position:relative;\"><a href=\"#-123-%EC%97%85%EC%BA%90%EC%8A%A4%ED%8C%85%EA%B3%BC-%EB%8F%99%EC%A0%81-%EB%B0%94%EC%9D%B8%EB%94%A9\" aria-label=\" 123 업캐스팅과 동적 바인딩 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 12.3 업캐스팅과 동적 바인딩</h2>\n<h3 id=\"-1231-같은-메시지-다른-메서드\" style=\"position:relative;\"><a href=\"#-1231-%EA%B0%99%EC%9D%80-%EB%A9%94%EC%8B%9C%EC%A7%80-%EB%8B%A4%EB%A5%B8-%EB%A9%94%EC%84%9C%EB%93%9C\" aria-label=\" 1231 같은 메시지 다른 메서드 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 12.3.1 같은 메시지, 다른 메서드</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@RequiredArgsConstructor\npublic class Professor {\n\n    private final String name;\n\n    private final Lecture lecture;\n\n    public String compileStatistics() {\n        return String.format(&quot;[%s] %s - Avg: %.1f&quot;, name, lecture.evaluate(), lecture.average());\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>업캐스팅\n<ul>\n<li>부모 클래스 타입으로 선언된 변수에 자식 클래스의 인스턴스를 할당하는 것이 가능</li>\n<li>서로 다른 클래스의 인스턴스를 동일한 타입에 할당하는 것을 가능하게 해준다.</li>\n</ul>\n</li>\n<li>동적 바인딩\n<ul>\n<li>선언된 변수의 타입이 아니라 메시지를 수신하는 객체의 타입에 따라 실행되는 메서드가 결정</li>\n<li>코드를 변경하지 않고도 실행되는 메서드를 변경할 수 있다.</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-1232-업캐스팅\" style=\"position:relative;\"><a href=\"#-1232-%EC%97%85%EC%BA%90%EC%8A%A4%ED%8C%85\" aria-label=\" 1232 업캐스팅 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 12.3.2 업캐스팅</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">Lecture lecture = new GradeLecture(...);</code>\n        </deckgo-highlight-code>\n<ul>\n<li>명시적으로 타입을 변환하지 않고도 부모 클래스 타입의 참조 변수에 자식 클래스의 인스턴스를 대입할 수 있게 허용</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class Professor {\n    public Professor(String name, Lecture lecture) {...}\n}\n\nProfessor professor = new Professor(&quot;다익스트라&quot;, new GradeLecture(...));</code>\n        </deckgo-highlight-code>\n<ul>\n<li>부모 클래스 타입으로 선언된 파라미터에 자식 클래스의 인스턴스를 전달하는 것도 가능</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">Lecture lecture = new GradeLecture(...);\nGradeLecture gradeLecture = (GradeLecture)lecture;</code>\n        </deckgo-highlight-code>\n<ul>\n<li>다운캐스팅\n<ul>\n<li>부모 클래스의 인스턴스를 자식 클래스 타입으로 변환하기 위해서는 명시적인 타입 캐스팅이 필요</li>\n</ul>\n</li>\n<li><code>Professor</code>는 <code>Lecture</code>를 상속받는 어떤 자식 클래스와도 협력할 수 있는 무한한 확장 가능성을 지닌다.\n<ul>\n<li>설계가 유연하고 확장이 용이</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-1233-동적-바인딩\" style=\"position:relative;\"><a href=\"#-1233-%EB%8F%99%EC%A0%81-%EB%B0%94%EC%9D%B8%EB%94%A9\" aria-label=\" 1233 동적 바인딩 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 12.3.3 동적 바인딩</h3>\n<p>컴파일타임에 호출할 함수를 결정하는 방식</p>\n<ul>\n<li><strong>정적 바인딩(static binding)</strong></li>\n<li><strong>초기 바인딩(early binding)</strong></li>\n<li><strong>컴파일타임 바인딩(compile-time binding)</strong></li>\n</ul>\n<p>런타임에 실행될 메서드를 결정하는 방식</p>\n<ul>\n<li><strong>동적 바인딩(dynamic binding)</strong></li>\n<li><strong>지연 바인딩(late binding)</strong></li>\n</ul>\n<h2 id=\"-124-동적-메서드-탐색과-다형성\" style=\"position:relative;\"><a href=\"#-124-%EB%8F%99%EC%A0%81-%EB%A9%94%EC%84%9C%EB%93%9C-%ED%83%90%EC%83%89%EA%B3%BC-%EB%8B%A4%ED%98%95%EC%84%B1\" aria-label=\" 124 동적 메서드 탐색과 다형성 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 12.4 동적 메서드 탐색과 다형성</h2>\n<p>객체지향 시스템은 다음 규칙에 따라 실행할 메서드를 선택</p>\n<ul>\n<li>메시지를 수신한 객체는 먼저 자신을 생성한 클래스에 적합한 메서드가 존재하는지 검사한다.\n<ul>\n<li>존재하면 메서드를 실행하고 탐색 종료</li>\n</ul>\n</li>\n<li>메서드를 찾지 못했다면 부모 클래스에서 메서드 탐색을 계속한다.\n<ul>\n<li>이 과정은 적합한 메서드를 찾을 때까지 상속 계층을 따라 올라가며 계속된다.</li>\n</ul>\n</li>\n<li>상속 계층의 가장 최상위 클래스에 이르렀지만 메서드를 발견하지 못한 경우 예외를 발생시키며 탐색을 중단</li>\n</ul>\n<p>객체가 메시지를 수신하면 컴파일러는 **self 참조(self reference)**라는 임시 변수를 자동으로 생성한 후 메시지를 수신한 객체를 가리키도록 설정</p>\n<ul>\n<li>java의 <code>this</code></li>\n</ul>\n<p>동적 메서드 탐색은 두 가지 원리로 구성</p>\n<ol>\n<li><strong>자동적인 메시지 위임</strong></li>\n<li><strong>동적인 문맥</strong> 사용</li>\n</ol>\n<h3 id=\"-1241-자동적인-메시지-위임\" style=\"position:relative;\"><a href=\"#-1241-%EC%9E%90%EB%8F%99%EC%A0%81%EC%9D%B8-%EB%A9%94%EC%8B%9C%EC%A7%80-%EC%9C%84%EC%9E%84\" aria-label=\" 1241 자동적인 메시지 위임 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 12.4.1 자동적인 메시지 위임</h3>\n<ul>\n<li>상속 계층을 정의하는 것은 메서드 탐색 경로를 정의하는 것과 동일</li>\n<li>일부 언어들은 상속이 아닌 다른 방법을 이용해 메시지를 자동으로 위임할 수 있는 메커니즘을 제공\n<ul>\n<li>루비의 모듈(module)</li>\n<li>스몰토크와 스칼라의 트레이트(trait)</li>\n<li>스위프트의 프로토콜(protocol)과 확장(extension) 메커니즘</li>\n</ul>\n</li>\n<li>자식 클래스에서 어떤 메서드를 구현하고 있느냐에 따라 부모 클래스에 구현된 메서드의 운명이 결정되기도 함.\n<ul>\n<li>자식 클래스에서 부모 클래스의 방향으로 자동으로 메시지 처리가 위임되기 때문</li>\n</ul>\n</li>\n<li>동일한 시그니처를 가지는 자식 클래스의 메서드는 부모 클래스의 메서드를 감추지만 이름만 같고 시그니처가 완전히 동일하지 않은 메서드들은 상속 계층에 걸쳐 사이좋게 공존할 수도 있다.\n<ul>\n<li>메서드 오버로딩</li>\n</ul>\n</li>\n</ul>\n<h4 id=\"-메서드-오버라이딩\" style=\"position:relative;\"><a href=\"#-%EB%A9%94%EC%84%9C%EB%93%9C-%EC%98%A4%EB%B2%84%EB%9D%BC%EC%9D%B4%EB%94%A9\" aria-label=\" 메서드 오버라이딩 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🎈 메서드 오버라이딩</h4>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">Lecture lecture = new Lecture(...);\nlecture.evaluate();</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>Lecture</code> 클래스 안에 <code>evaluate</code> 메서드가 존재하기 때문에 시스템은 메서드를 실행한 후 메서드 탐색을 종료</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">Lecture lecture = new GradeLecture(...);\nlecture.evaluate();</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>GradeLecture</code> 클래스 안에 <code>evaluate</code> 메서드가 존재하기 때문에 먼저 발견된 메서드가 실행</li>\n<li>자식 클래스의 메서드가 부모 클래스의 메서드를 감추는 것처럼 보이게 된다.</li>\n</ul>\n<h4 id=\"-메서드-오버로딩\" style=\"position:relative;\"><a href=\"#-%EB%A9%94%EC%84%9C%EB%93%9C-%EC%98%A4%EB%B2%84%EB%A1%9C%EB%94%A9\" aria-label=\" 메서드 오버로딩 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🎈 메서드 오버로딩</h4>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">GradeLecture lecture = new GradeLecture(...);\nlecture.average(&quot;A&quot;);</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>GradeLecture</code>에서 종료</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">Lecture lecture = new GradeLecture(...);\nlecture.average();</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>Lecture</code>에서 종료</li>\n<li>클라이언트의 관점에서 오버로딩된 모든 메서드를 호출할 수 있다.</li>\n</ul>\n<p>대부분의 사람들은 하나의 클래스 안에서 같은 이름을 가진 메서드들을 정의하는 것은 메서드 오버로딩으로 생각하고 상속 계층 사이에서 같은 이름을 가진 메서드를 정의하는 것은 메서드 오버로딩으로 생각하지 않는 경향이 있다.</p>\n<ul>\n<li>일부 언어에서 상속 계층 사이의 메서드 오버로딩을 지원하지 않기 때문\n<ul>\n<li>C++의 <strong>이름 숨기기(name hiding)</strong></li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-1242-동적인-문맥\" style=\"position:relative;\"><a href=\"#-1242-%EB%8F%99%EC%A0%81%EC%9D%B8-%EB%AC%B8%EB%A7%A5\" aria-label=\" 1242 동적인 문맥 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 12.4.2 동적인 문맥</h3>\n<p>동적인 문맥을 결정하는 것은 바로 메시지를 수신한 객체를 가리키는 self 참조</p>\n<ul>\n<li>self 참조가 동적 문맥을 결정한다는 사실은 종종 어떤 메서드가 실행될지를 예상하기 어렵게 만든다.\n<ul>\n<li><strong>self 전송(self send)</strong></li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class Lecture {\n\n    public String stats() {\n        return String.format(&quot;Title: %s, Evaluation Method: %s&quot;, title, getEvaluationMethod());\n    }\n\n    public String getEvaluationMethod() {\n        return &quot;Pass or Fail&quot;;\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>getEvaluationMethod()</code>라는 구문은 현재 클래스의 메서드를 호출하는 것이 아니라 현재 객체에게 <code>getEvaluationMethod</code> 메시지를 전송하는 것이다.\n<ul>\n<li>현재 객체\n<ul>\n<li>self 참조가 가리키는 객체</li>\n<li>stats 메시지를 수신했던 객체</li>\n</ul>\n</li>\n<li>self 전송\n<ul>\n<li>self 참조가 가리키는 바로 그 객체에서부터 메시지 탐색을 다시 시작</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class GradeLecture extends Lecture {\n\n    @Override\n    public String getEvaluationMethod() {\n        return &quot;Grade&quot;;\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>GradeLecture</code>에 <code>stats</code> 메시지를 전송\n<ul>\n<li><code>Lecture</code> 클래스의 <code>stats</code> 메서드와 <code>GradeLecture</code> 클래스의 <code>getEvaluationMethod</code> 메서드의 실행 결과를 조합한 문자열이 반환</li>\n</ul>\n</li>\n<li>self 전송은 자식 클래스에서 부모 클래스 방향으로 진행되는 동적 메서드 탐색 경로를 다시 self 참조가 가리키는 원래의 자식 클래스로 이동\n<ul>\n<li>최악의 경우에는 실제로 실행될 메서드를 이해하기 위해 상속 계층 전체를 훑어가며 코드를 이해해야 하는 상황이 발생</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-1243-이해할-수-없는-메시지\" style=\"position:relative;\"><a href=\"#-1243-%EC%9D%B4%ED%95%B4%ED%95%A0-%EC%88%98-%EC%97%86%EB%8A%94-%EB%A9%94%EC%8B%9C%EC%A7%80\" aria-label=\" 1243 이해할 수 없는 메시지 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 12.4.3 이해할 수 없는 메시지</h3>\n<p>객체가 메시지를 이해할 수 없다면 어떻게 할까❓</p>\n<ul>\n<li>정적 타입 언어와 동적 타입 언어에 따라 달라진다.</li>\n</ul>\n<h4 id=\"-정적-타입-언어와-이해할-수-없는-메시지\" style=\"position:relative;\"><a href=\"#-%EC%A0%95%EC%A0%81-%ED%83%80%EC%9E%85-%EC%96%B8%EC%96%B4%EC%99%80-%EC%9D%B4%ED%95%B4%ED%95%A0-%EC%88%98-%EC%97%86%EB%8A%94-%EB%A9%94%EC%8B%9C%EC%A7%80\" aria-label=\" 정적 타입 언어와 이해할 수 없는 메시지 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🎈 정적 타입 언어와 이해할 수 없는 메시지</h4>\n<p>정적 타입 언어에서는 코드를 컴파일할 때 상속 계층 안의 클래스들이 메시지를 이해할 수 있는지 여부를 판단</p>\n<ul>\n<li>상속 계층 전체를 탐색한 후에도 메시지를 처리할 수 있는 메서드를 발견하지 못했다면 컴파일 에러 발생</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">Lecture lecture = new GradeLecture(...);\nlecture.unknownMessage(); // 컴파일 에러!</code>\n        </deckgo-highlight-code>\n<h4 id=\"-동적-타입-언어와-이해할-수-없는-메시지\" style=\"position:relative;\"><a href=\"#-%EB%8F%99%EC%A0%81-%ED%83%80%EC%9E%85-%EC%96%B8%EC%96%B4%EC%99%80-%EC%9D%B4%ED%95%B4%ED%95%A0-%EC%88%98-%EC%97%86%EB%8A%94-%EB%A9%94%EC%8B%9C%EC%A7%80\" aria-label=\" 동적 타입 언어와 이해할 수 없는 메시지 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🎈 동적 타입 언어와 이해할 수 없는 메시지</h4>\n<p>동적 타입 언어에는 컴파일 단계가 존재하지 않기 때문에 실제로 코드를 실행해보기 전에는 메시지 처리 가능 여부를 판단할 수 없다.</p>\n<ul>\n<li>상속 계층을 거슬러 올라가며 메서드를 탐색 후, 예외를 던진다.</li>\n<li>예외를 던지지 않고 응답할 수 있는 메서드를 구현할 수도 있다.</li>\n</ul>\n<p>좀 더 순수한 관점에서 객체지향 패러다임을 구현한다.</p>\n<ul>\n<li>메시지가 선언된 인터페이스와 메서드가 정의된 구현을 분리할 수 있다.</li>\n<li>코드를 이해하고 수정하기 어렵게 만들고, 디버깅 과정을 복잡화게 만든다.</li>\n</ul>\n<h3 id=\"-1244-self-대-super\" style=\"position:relative;\"><a href=\"#-1244-self-%EB%8C%80-super\" aria-label=\" 1244 self 대 super permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 12.4.4 self 대 super</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class GradeLecture extends Lecture {\n\n    @Override\n    public String evaluate() {\n        return super.evaluate() + &quot;, &quot; + gradesStatistics();\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>super 참조를 이용해 '메시지를 전송'한다.</li>\n<li>부모 클래스의 메서드가 아니라 더 상위에 위치한 조상 클래스의 메서드일 수도 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class FormattedGradeLecture extends GradeLecture {\n\n    public FormattedGradeLecture(int pass, String title, List&lt;Integer&gt; scores, List&lt;Grade&gt; grades) {\n        super(pass, title, scores, grades);\n    }\n\n    public String formatAverage() {\n        return String.format(&quot;Avg: %1.1f&quot;, super.average());\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>super.average()</code>에 의해 실행되는 메서드는 <code>GradeLecture</code>의 부모 클래스인 <code>Lecture</code>의 <code>average</code> 메서드이다.</li>\n</ul>\n<p>super 참조의 정확한 의도는 '지금 이 클래스의 부모 클래스에서부터 메서드 탐색을 시작하세요'다.</p>\n<ul>\n<li>실행하고자 하는 메서드가 반드시 부모 클래스에 위치하지 않아도 되는 유연성을 제공</li>\n<li>super 전송(super send)</li>\n</ul>\n<p>self 전송이 메시지를 수신하는 객체의 클래스에 따라 메서드를 탐색할 시작 위치를 동적으로 결정하는 데 비해 super 전송은 항상 메시지를 전송하는 클래스의 부모 클래스에서부터 시작된다.</p>\n<ul>\n<li>super 전송의 경우에는 컴파일 시점에 미리 결정해 놓을 수 있다.</li>\n<li>super 참조는 부모 클래스의 코드에 접근할 수 있게 함으로써 중복 코드를 제거할 수 있게 한다.</li>\n</ul>\n<h2 id=\"-125-상속-대-위임\" style=\"position:relative;\"><a href=\"#-125-%EC%83%81%EC%86%8D-%EB%8C%80-%EC%9C%84%EC%9E%84\" aria-label=\" 125 상속 대 위임 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 12.5 상속 대 위임</h2>\n<h3 id=\"-1251-위임과-self-참조\" style=\"position:relative;\"><a href=\"#-1251-%EC%9C%84%EC%9E%84%EA%B3%BC-self-%EC%B0%B8%EC%A1%B0\" aria-label=\" 1251 위임과 self 참조 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 12.5.1 위임과 self 참조</h3>\n<p>self 참조는 항상 메시지를 수신한 객체를 가리킨다.</p>\n<ul>\n<li>메서드 탐색 중에는 자식 클래스의 인스턴스와 부모 클래스의 인스턴스가 동일한 self 참조를 공유하는 것으로 봐도 무방하다.</li>\n</ul>\n<p>위임(delegation)</p>\n<ul>\n<li>자신이 수신한 메시지를 다른 객체에게 동일하게 전달해서 처리를 요청하는 것</li>\n<li>자신이 정의하지 않거나 처리할 수 없는 속성 또는 메서드의 탐색 과정을 다른 객체로 이동시키기 위해 사용</li>\n<li>항상 현재의 실행 문맥을 가리키는 self 참조를 인자로 전달\n<ul>\n<li>포워딩은 self 참조를 전달하지 않음</li>\n</ul>\n</li>\n<li>위임의 정확한 용도는 클래스를 이용한 상속 관계를 객체 사이의 합성 관계로 대체해서 다형성을 구현하는 것</li>\n</ul>\n<h3 id=\"-1252-프로토타입-기반의-객체지향-언어\" style=\"position:relative;\"><a href=\"#-1252-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85-%EA%B8%B0%EB%B0%98%EC%9D%98-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EC%96%B8%EC%96%B4\" aria-label=\" 1252 프로토타입 기반의 객체지향 언어 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 12.5.2 프로토타입 기반의 객체지향 언어</h3>\n<p>클래스가 존재하지 않고 오직 객체만 존재하는 프로토타입 기반의 객체지향 언어에서 상속을 구현하는 유일한 방법은 객체 사이의 위임을 이용하는 것이다.</p>\n<ul>\n<li>메서드를 탐색하는 과정은 클래스 기반 언어의 상속과 거의 동일</li>\n<li>객체지향 패러다임에서 클래스가 필수 요소가 아님.\n<ul>\n<li>javascript는 오직 객체들 사이의 메시지 위임만을 이용해 다형성을 구현</li>\n</ul>\n</li>\n</ul>\n<p>중요한 것은 클래스 기반의 상속과 객체 기반의 위임 사이에 기본 개념과 메커니즘을 공유한다는 점</p>","excerpt":"상속의 목적이 코드 재사용이라면 사용하지 말아야 한다. 다형성이 런타임에 메시지를 처리하기에 적합한 메서드를 동적으로 탐색하는 과정을 통해 구현되며, 상속이 이런 메서드를 찾기 위한 일종의 탐색 경로를 클래스 계층의 형태로 구현된다. 📖 12.1 다형성 많은 형태를 가질 수 있는 능력 Universal 다형성 Parametric 다형성 클래스의 인스턴스 변수나 메서드의 매개변수 타입을 임의의 타입으로 선언한 후 사용하는 시점에 구체적인 타입으로 지정하는 방식 제네릭 프로그래밍 Inclustion…","fields":{"slug":"/backend/object/chapter12/다형성/"},"frontmatter":{"title":"Object - 12장 다형성","thumbnail":{"childImageSharp":{"fluid":{"src":"/static/dd0e1990925e942697544e2bdcd9332e/9b73b/object.png"}}},"draft":false,"category":"Back-End","tags":["java"],"date":"November 12, 2023"}}}},"staticQueryHashes":["2374173507","2996537568","3691437124"]}