{"componentChunkName":"component---src-containers-post-index-tsx","path":"/backend/kotlin-in-action/3장-함수_정의와_호출/","result":{"pageContext":{"next":{"id":"06700cd2-2245-5186-9a8f-f542df019318","html":"<h2 id=\"-21-기본-요소-함수와-변수\" style=\"position:relative;\"><a href=\"#-21-%EA%B8%B0%EB%B3%B8-%EC%9A%94%EC%86%8C-%ED%95%A8%EC%88%98%EC%99%80-%EB%B3%80%EC%88%98\" aria-label=\" 21 기본 요소 함수와 변수 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>📖 2.1 기본 요소: 함수와 변수</h2>\n<h3 id=\"-211-첫-번째-코틀린-프로그램-작성-hello-world\" style=\"position:relative;\"><a href=\"#-211-%EC%B2%AB-%EB%B2%88%EC%A7%B8-%EC%BD%94%ED%8B%80%EB%A6%B0-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EC%9E%91%EC%84%B1-hello-world\" aria-label=\" 211 첫 번째 코틀린 프로그램 작성 hello world 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>🔖 2.1.1 첫 번째 코틀린 프로그램 작성: Hello, World!</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    fun main() {\n        println(&quot;Hello World!&quot;)\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>함수를 모든 코틀린 파일의 최상위 수준에 정의 가능</li>\n<li>main에 인자가 없어도 된다.</li>\n<li>간결성 강조</li>\n<li>세미콜론(;)을 붙이지 않는 것을 더 권장한다.</li>\n</ul>\n<h3 id=\"-212-파라미터와-반환값이-있는-함수-선언\" style=\"position:relative;\"><a href=\"#-212-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0%EC%99%80-%EB%B0%98%ED%99%98%EA%B0%92%EC%9D%B4-%EC%9E%88%EB%8A%94-%ED%95%A8%EC%88%98-%EC%84%A0%EC%96%B8\" aria-label=\" 212 파라미터와 반환값이 있는 함수 선언 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>🔖 2.1.2 파라미터와 반환값이 있는 함수 선언</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    fun max(a: Int, b: Int): Int {\n        return if (a &gt; b) a else b\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>파라미터 이름이 먼저 오고 그 뒤에 타입 지정\n<ul>\n<li>콜론(:)으로 구분</li>\n</ul>\n</li>\n<li>함수의 반환 타입은 파라미터 목록을 닫는 괄호 다음에 옴.</li>\n<li>위와 같은 코드를 블록 본문 함수(block body function)이라고 부름.</li>\n</ul>\n<h3 id=\"-213-식-본문을-사용해-함수를-더-간결하게-정의\" style=\"position:relative;\"><a href=\"#-213-%EC%8B%9D-%EB%B3%B8%EB%AC%B8%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%B4-%ED%95%A8%EC%88%98%EB%A5%BC-%EB%8D%94-%EA%B0%84%EA%B2%B0%ED%95%98%EA%B2%8C-%EC%A0%95%EC%9D%98\" aria-label=\" 213 식 본문을 사용해 함수를 더 간결하게 정의 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>🔖 2.1.3 식 본문을 사용해 함수를 더 간결하게 정의</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun max(a: Int, b: Int): Int = if (a &gt; b) a else b</code>\n        </deckgo-highlight-code>\n<ul>\n<li>위와 같은 함수를 본문 함수(expression body function)이라고 부름.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun max(a: Int, b: Int) = if (a &gt; b) a else b</code>\n        </deckgo-highlight-code>\n<ul>\n<li>반환 타입이 없지만 컴파일러가 타입 추론(inference)하여 반환 타입을 지정\n<ul>\n<li>이 경우, 식 본문 함수만 반환 타입이 생략 가능</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-214-데이터를-저장하기-위해-변수-선언\" style=\"position:relative;\"><a href=\"#-214-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-%EC%A0%80%EC%9E%A5%ED%95%98%EA%B8%B0-%EC%9C%84%ED%95%B4-%EB%B3%80%EC%88%98-%EC%84%A0%EC%96%B8\" aria-label=\" 214 데이터를 저장하기 위해 변수 선언 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>🔖 2.1.4 데이터를 저장하기 위해 변수 선언</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val question: String = &quot;삶, 우주, 그리고 모든 것에 대한 궁극적인 질문&quot;\nval answer: Int = 42</code>\n        </deckgo-highlight-code>\n<ul>\n<li>변수 선언은 val or var로 가능하다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val question = &quot;삶, 우주, 그리고 모든 것에 대한 궁극적인 질문&quot;\nval answer = 42</code>\n        </deckgo-highlight-code>\n<ul>\n<li>타입 선언 생략 가능</li>\n</ul>\n<h3 id=\"-215-변수를-읽기-전용-변수나-재대입-가능-변수로-표시\" style=\"position:relative;\"><a href=\"#-215-%EB%B3%80%EC%88%98%EB%A5%BC-%EC%9D%BD%EA%B8%B0-%EC%A0%84%EC%9A%A9-%EB%B3%80%EC%88%98%EB%82%98-%EC%9E%AC%EB%8C%80%EC%9E%85-%EA%B0%80%EB%8A%A5-%EB%B3%80%EC%88%98%EB%A1%9C-%ED%91%9C%EC%8B%9C\" aria-label=\" 215 변수를 읽기 전용 변수나 재대입 가능 변수로 표시 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>🔖 2.1.5 변수를 읽기 전용 변수나 재대입 가능 변수로 표시</h3>\n<h4 id=\"valvalue\" style=\"position:relative;\"><a href=\"#valvalue\" aria-label=\"valvalue 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>val(value)</h4>\n<ul>\n<li>읽기 전용 참조(read-only reference)를 선언</li>\n<li>단 한 번만 대입 가능</li>\n<li>코틀린에서는 모든 변수를 val 키워드를 사용해 선언하는 방식을 지켜야 함.</li>\n</ul>\n<h4 id=\"varvariable\" style=\"position:relative;\"><a href=\"#varvariable\" aria-label=\"varvariable 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>var(variable)</h4>\n<ul>\n<li>재대입 가능한 참조(reassignable reference)를 선언</li>\n<li>초기화 이후, 다른 값 대입 가능</li>\n<li>반드시 필요할 때에만 var로 변경</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    fun main() {\n        val result: String\n        if (canPerformOperation()) {\n            result = &quot;Success&quot;\n        }\n        else {\n            result = &quot;Can&#39;t perform operation&quot;\n        }\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>val 참조가 가리키는 객체의 내부 값은 변경될 수 있음.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    fun main() {\n        var answer = 42\n        answer = &quot;no answer&quot;\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>var는 변수의 값은 변경할 수 있지만 변수의 타입은 고정된다.</li>\n</ul>\n<h3 id=\"-216-더-쉽게-문자열-형식-지정-문자열-템플릿\" style=\"position:relative;\"><a href=\"#-216-%EB%8D%94-%EC%89%BD%EA%B2%8C-%EB%AC%B8%EC%9E%90%EC%97%B4-%ED%98%95%EC%8B%9D-%EC%A7%80%EC%A0%95-%EB%AC%B8%EC%9E%90%EC%97%B4-%ED%85%9C%ED%94%8C%EB%A6%BF\" aria-label=\" 216 더 쉽게 문자열 형식 지정 문자열 템플릿 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>🔖 2.1.6 더 쉽게 문자열 형식 지정: 문자열 템플릿</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    fun main() {\n        val input = readln()\n        val name = if (input.isNotBlank()) input else &quot;Kotlin&quot;\n        println(&quot;Hello, $name!&quot;)\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린 또한 변수 이름 앞에 $를 덧붙이면 변수를 문자열 안에 참조할 수 있다.</li>\n<li>$ 문자를 문자열에 넣고 싶으면 \\를 사용해 escape 시키면 됨.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    fun main() {\n        val name = readln()\n        println(&quot;Hello, ${if (name.isBlank()) &quot;someone&quot; else name}!&quot;)\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>중괄호로 둘러쌓인 식 안에서 여전히 큰따옴표를 사용할 수 있다.</li>\n</ul>\n<h2 id=\"-22-행동과-데이터-캡슐화-클래스와-프로퍼티\" style=\"position:relative;\"><a href=\"#-22-%ED%96%89%EB%8F%99%EA%B3%BC-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%BA%A1%EC%8A%90%ED%99%94-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0\" aria-label=\" 22 행동과 데이터 캡슐화 클래스와 프로퍼티 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>📖 2.2 행동과 데이터 캡슐화: 클래스와 프로퍼티</h2>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Person(val name: String)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>java의 getter와 생성자가 한줄로 요약된다.</li>\n<li>public visibility modifier가 사라진다.</li>\n<li>코틀린의 기본 가시성은 public이다.</li>\n</ul>\n<h3 id=\"-221-클래스와-데이터를-연관시키고-접근-가능하게-만들기-프로퍼티\" style=\"position:relative;\"><a href=\"#-221-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-%EC%97%B0%EA%B4%80%EC%8B%9C%ED%82%A4%EA%B3%A0-%EC%A0%91%EA%B7%BC-%EA%B0%80%EB%8A%A5%ED%95%98%EA%B2%8C-%EB%A7%8C%EB%93%A4%EA%B8%B0-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0\" aria-label=\" 221 클래스와 데이터를 연관시키고 접근 가능하게 만들기 프로퍼티 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>🔖 2.2.1 클래스와 데이터를 연관시키고, 접근 가능하게 만들기: 프로퍼티</h3>\n<ul>\n<li>클래스라는 개념은 데이터를 캡슐화하고 캡슐화한 데이터를 다루는 코드를 한 주체 안에 가두는 것이다.</li>\n<li>자바에서는 필드와 접근자를 한데 묶어 property라고 부른다.</li>\n<li>코틀린 property는 자바의 필드와 접근자 메서드를 완전히 대신한다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Person(\n    val name: String,\n    var isStudent: Boolean\n)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>val, var를 같이 선언할 수 있다.</li>\n<li>val는 getter를 만들어내고, var는 getter와 setter를 만들어낸다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    fun main() {\n        val person = Person(&quot;Bob&quot;, true)\n        println(person.name)\n        println(person.isStudent)\n        person.isStudent = false\n        println(person.isStudent)\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>new 키워드 사용하지 않고 생성자 호출 가능</li>\n<li>프로퍼티 이름을 직접 사용해도 getter, setter 호출 가능</li>\n</ul>\n<h3 id=\"-222-프로퍼티-값을-저장하지-않고-계산-커스텀-접근자\" style=\"position:relative;\"><a href=\"#-222-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0-%EA%B0%92%EC%9D%84-%EC%A0%80%EC%9E%A5%ED%95%98%EC%A7%80-%EC%95%8A%EA%B3%A0-%EA%B3%84%EC%82%B0-%EC%BB%A4%EC%8A%A4%ED%85%80-%EC%A0%91%EA%B7%BC%EC%9E%90\" aria-label=\" 222 프로퍼티 값을 저장하지 않고 계산 커스텀 접근자 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>🔖 2.2.2 프로퍼티 값을 저장하지 않고 계산: 커스텀 접근자</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Rectangle(var height: Int, var width: Int) {\n    val isSquare: Boolean\n        get() {\n            return height == width\n        }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>isSquare 프로퍼티는 on the go 프로퍼티이다.</li>\n<li>커스텀 게터를 정의하는 방식과 클래스 안에 파라미터가 없는 함수를 정의하는 방식은 비슷하다.\n<ul>\n<li>구현이나 성능 차이 없음.</li>\n<li>가독성 차이</li>\n<li>클래스의 특성을 기술하고 싶다면 프로퍼티로 정의</li>\n<li>클래스의 행동을 기술하고 싶다면 멤버 함수 선택</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-223-코틀린-소스코드-구조-디렉터리와-패키지\" style=\"position:relative;\"><a href=\"#-223-%EC%BD%94%ED%8B%80%EB%A6%B0-%EC%86%8C%EC%8A%A4%EC%BD%94%EB%93%9C-%EA%B5%AC%EC%A1%B0-%EB%94%94%EB%A0%89%ED%84%B0%EB%A6%AC%EC%99%80-%ED%8C%A8%ED%82%A4%EC%A7%80\" aria-label=\" 223 코틀린 소스코드 구조 디렉터리와 패키지 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>🔖 2.2.3 코틀린 소스코드 구조: 디렉터리와 패키지</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">package com.bottleh.studycodecollection.kotlin.chap2\n\nclass Rectangle(var height: Int, var width: Int) {\n    val isSquare: Boolean\n        get() {\n            return height == width\n        }\n}\n\nfun createUnitSquare(): Rectangle {\n    return Rectangle(1, 1)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>같은 패키지에 속해 있다면 다른 파일에서 정의한 선언일지라도 직접 사용할 수 있다.</li>\n<li>다른 패키지에 정의한 선언을 사용하려면 import 키워드를 사용해서 다른 패키지를 불러올 수 있다.</li>\n<li>자바에서는 패키지의 구조와 디렉터리 계층구조가 같아야 한다.</li>\n<li>코틀린에서는 패키지와 디렉터리 구조가 맞아 떨어질 필요가 없다.\n<ul>\n<li>다만, 자바와 같이 패키지별로 디렉터리를 구성하는 편이 낫다.</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"-23-선택-표현과-처리-이넘과-when\" style=\"position:relative;\"><a href=\"#-23-%EC%84%A0%ED%83%9D-%ED%91%9C%ED%98%84%EA%B3%BC-%EC%B2%98%EB%A6%AC-%EC%9D%B4%EB%84%98%EA%B3%BC-when\" aria-label=\" 23 선택 표현과 처리 이넘과 when 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>📖 2.3 선택 표현과 처리: 이넘과 when</h2>\n<h3 id=\"-231-이넘-클래스와-이넘-상수-정의\" style=\"position:relative;\"><a href=\"#-231-%EC%9D%B4%EB%84%98-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%EC%9D%B4%EB%84%98-%EC%83%81%EC%88%98-%EC%A0%95%EC%9D%98\" aria-label=\" 231 이넘 클래스와 이넘 상수 정의 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>🔖 2.3.1 이넘 클래스와 이넘 상수 정의</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">enum class Color {\n    RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>java는 enum이지만 kotlin은 enum class다.</li>\n<li>enum은 소프트 키워드라서 class 앞이 아니라면 다른곳에서 사용할 수 없다.</li>\n<li>class는 하드 키워드라서 클래스를 표현하는 변수 등을 정의할 때 clazz 등을 사용해야 한다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">package com.bottleh.studycodecollection.kotlin.chap2\n\nenum class Color(\n    val r: Int, val g: Int, val b: Int\n) {\n    RED(255, 0, 0), \n    ORANGE(255, 165, 0),\n    YELLOW(255, 255, 0),\n    GREEN(0, 255, 0),\n    BLUE(0, 0, 255),\n    INDIGO(75, 0, 130),\n    VIOLET(238, 130, 238);\n    \n    fun rgb() = (r * 256 + g) * 256 + b\n    fun printColor() = println(&quot;$this is ${rgb()}&quot;)\n}\n\nfun main() {\n    println(Color.BLUE.rgb())\n    Color.GREEN.printColor()\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>enum class 안에 메서드를 정의하는 경우 반드시 이넘 상수 목록과 메서드 정의 사이에 세미콜론을 넣어야 한다.\n<ul>\n<li>코틀린에서 세미콜론이 필수인 유일한 경우다.</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-232-when으로-이넘-클래스-다루기\" style=\"position:relative;\"><a href=\"#-232-when%EC%9C%BC%EB%A1%9C-%EC%9D%B4%EB%84%98-%ED%81%B4%EB%9E%98%EC%8A%A4-%EB%8B%A4%EB%A3%A8%EA%B8%B0\" aria-label=\" 232 when으로 이넘 클래스 다루기 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>🔖 2.3.2 when으로 이넘 클래스 다루기</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun getMnemonic(color: Color) = \n    when (color) {\n        Color.RED -&gt; &quot;Richard&quot;\n        Color.ORANGE -&gt; &quot;Of&quot;\n        Color.YELLOW -&gt; &quot;York&quot;\n        Color.GREEN -&gt; &quot;Gave&quot;\n        Color.BLUE -&gt; &quot;Battle&quot;\n        Color.INDIGO -&gt; &quot;In&quot;\n        Color.VIOLET -&gt; &quot;Vain&quot;\n    }\n\nfun main() {\n    println(getMnemonic(Color.BLUE))\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>java와 달리 break를 넣지 않아도 된다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun measureColor() = Color.ORANGE\n\nfun getWarmthFromSensor(): String {\n    val color = measureColor()\n    return when(color) {\n        Color.RED, Color.ORANGE, Color.YELLOW -&gt; &quot;warm (red = ${color.r})&quot;\n        Color.GREEN -&gt; &quot;neutral (green = ${color.g})&quot;\n        Color.BLUE, Color.INDIGO, Color.VIOLET -&gt; &quot;cold (blue = ${color.b})&quot;\n    }\n}\n\nfun main() {\n    println(getWarmthFromSensor())\n}</code>\n        </deckgo-highlight-code>\n<h3 id=\"-233-when식의-대상을-변수에-캡처\" style=\"position:relative;\"><a href=\"#-233-when%EC%8B%9D%EC%9D%98-%EB%8C%80%EC%83%81%EC%9D%84-%EB%B3%80%EC%88%98%EC%97%90-%EC%BA%A1%EC%B2%98\" aria-label=\" 233 when식의 대상을 변수에 캡처 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>🔖 2.3.3 when식의 대상을 변수에 캡처</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun getWarmthFromSensor() =\n    when(val color = measureColor()) {\n        Color.RED, Color.ORANGE, Color.YELLOW -&gt; &quot;warm (red = ${color.r})&quot;\n        Color.GREEN -&gt; &quot;neutral (green = ${color.g})&quot;\n        Color.BLUE, Color.INDIGO, Color.VIOLET -&gt; &quot;cold (blue = ${color.b})&quot;\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>when 식 대상 값을 변수에 넣을 수 있다.</li>\n<li>캡처한 변수의 프로퍼티에 접근 가능하다.</li>\n</ul>\n<h3 id=\"-234-when의-분기-조건에-임의의-객체-사용\" style=\"position:relative;\"><a href=\"#-234-when%EC%9D%98-%EB%B6%84%EA%B8%B0-%EC%A1%B0%EA%B1%B4%EC%97%90-%EC%9E%84%EC%9D%98%EC%9D%98-%EA%B0%9D%EC%B2%B4-%EC%82%AC%EC%9A%A9\" aria-label=\" 234 when의 분기 조건에 임의의 객체 사용 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>🔖 2.3.4 when의 분기 조건에 임의의 객체 사용</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun mix(c1: Color, c2: Color) =\n    when(setOf(c1, c2)) {\n        setOf(RED, YELLOW) -&gt; ORANGE\n        setOf(YELLOW, BLUE) -&gt; GREEN\n        setOf(BLUE, VIOLET) -&gt; INDIGO\n        else -&gt; throw Exception(&quot;Dirty color&quot;)\n    }\n\nfun main() {\n    println(mix(BLUE, YELLOW))\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>when의 분기 조건 부분에 식을 넣을 수 있기 때문에 많은 경우 코드를 더 간결하고 아름답게 작성할 수 있다.</li>\n</ul>\n<h3 id=\"-235-인자-없는-when-사용\" style=\"position:relative;\"><a href=\"#-235-%EC%9D%B8%EC%9E%90-%EC%97%86%EB%8A%94-when-%EC%82%AC%EC%9A%A9\" aria-label=\" 235 인자 없는 when 사용 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>🔖 2.3.5 인자 없는 when 사용</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun mixOptimized(c1: Color, c2: Color) =\n    when {\n        (c1 == RED &amp;&amp; c2 == YELLOW) || (c1 == YELLOW &amp;&amp; c2 == RED) -&gt; ORANGE\n        (c1 == YELLOW &amp;&amp; c2 == BLUE) || (c1 == BLUE &amp;&amp; c2 == YELLOW) -&gt; GREEN\n        (c1 == BLUE &amp;&amp; c2 == VIOLET) || (c1 == VIOLET &amp;&amp; c2 == BLUE) -&gt; INDIGO\n        \n        else -&gt; throw Exception(&quot;Dirty color&quot;)\n    }\n\nfun main() {\n    println(mixOptimized(BLUE, YELLOW))\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>인자가 없는 when 식을 사용하면 불필요한 객체 생성을 막을 수 있다.</li>\n<li>다만, 코드의 가독성은 떨어진다.</li>\n</ul>\n<h3 id=\"-236-스마트-캐스트-타입-검사와-타입-캐스트-조합\" style=\"position:relative;\"><a href=\"#-236-%EC%8A%A4%EB%A7%88%ED%8A%B8-%EC%BA%90%EC%8A%A4%ED%8A%B8-%ED%83%80%EC%9E%85-%EA%B2%80%EC%82%AC%EC%99%80-%ED%83%80%EC%9E%85-%EC%BA%90%EC%8A%A4%ED%8A%B8-%EC%A1%B0%ED%95%A9\" aria-label=\" 236 스마트 캐스트 타입 검사와 타입 캐스트 조합 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>🔖 2.3.6 스마트 캐스트: 타입 검사와 타입 캐스트 조합</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface Expr\n\nclass Num(val value: Int) : Expr\nclass Sum(val left: Expr, val right: Expr) : Expr</code>\n        </deckgo-highlight-code>\n<ul>\n<li>여러 타입의 식 객체를 아우르는 공통 타입 역할만 수행하는 인터페이스를 <strong>마커 인터페이스</strong>라고 부른다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun eval(e: Expr): Int {\n    if (e is Num) {\n        val n = e as Num // 불필요한 중복\n        return n.value\n    }\n    if (e is Sum) {\n        return eval(e.left) + eval(e.right)\n    }\n    throw IllegalArgumentException(&quot;Unknown expression&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린의 is 검사는 어떤 변수의 타입을 확인한 다음에 그 타입에 속한 멤버에 접근하기 위해 명시적으로 변수 타입을 변환하지 않아도 된다.</li>\n<li>실제로는 컴파일러가 타입을 대신 변환(스마트 캐스트)</li>\n</ul>\n<h3 id=\"-237-리팩터링-if를-when으로-변경\" style=\"position:relative;\"><a href=\"#-237-%EB%A6%AC%ED%8C%A9%ED%84%B0%EB%A7%81-if%EB%A5%BC-when%EC%9C%BC%EB%A1%9C-%EB%B3%80%EA%B2%BD\" aria-label=\" 237 리팩터링 if를 when으로 변경 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>🔖 2.3.7 리팩터링: if를 when으로 변경</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun eval(e: Expr): Int =\n    if (e is Num) {\n        e.value\n    } else if (e is Sum) {\n        eval(e.right) + eval(e.left)\n    } else {\n        throw IllegalArgumentException(&quot;Unknown expression&quot;)\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>if는 식이라서 삼항 연산자가 따로 없다.</li>\n<li>중괄호를 없애고 본문 구문을 사용해 작성 가능하다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun eval(e: Expr): Int =\n    if (e is Num) e.value\n    else if (e is Sum) eval(e.right) + eval(e.left)\n    else throw IllegalArgumentException(&quot;Unknown expression&quot;)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>if의 분기에 식이 하나밖에 없다면 중괄호를 생략해도 된다.</li>\n<li>블록을 사용한다면 블록의 마지막 식이 그 분기의 결괏값이다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun eval(e: Expr): Int =\n    when (e) {\n        is Num -&gt; e.value\n        is Sum -&gt; eval(e.right) + eval(e.left)\n        else -&gt; throw IllegalArgumentException(&quot;Unknown expression&quot;)\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>when으로 변경된 코드</li>\n</ul>\n<h3 id=\"-238-if와-when의-분기에서-블록-사용\" style=\"position:relative;\"><a href=\"#-238-if%EC%99%80-when%EC%9D%98-%EB%B6%84%EA%B8%B0%EC%97%90%EC%84%9C-%EB%B8%94%EB%A1%9D-%EC%82%AC%EC%9A%A9\" aria-label=\" 238 if와 when의 분기에서 블록 사용 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>🔖 2.3.8 if와 when의 분기에서 블록 사용</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun evalWithLogging(e: Expr): Int =\n    when (e) {\n        is Num -&gt; {\n            println(&quot;num: ${e.value}&quot;)\n            e.value\n        }\n        is Sum -&gt; {\n            val left = evalWithLogging(e.left)\n            val right = evalWithLogging(e.right)\n            println(&quot;sum: $left + $right&quot;)\n            left + right\n        }\n        else -&gt; throw IllegalArgumentException(&quot;Unknown expression&quot;)\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>if나 when 모두 분기에 블록을 사용할 수 있다.</li>\n<li><em>블록의 마지막 식이 블록의 결과</em> 라는 규칙은 블록이 값을 만들어내야 하는 경우 항상 성립한다.</li>\n</ul>\n<h2 id=\"-24-대상-이터레이션-while과-for-루프\" style=\"position:relative;\"><a href=\"#-24-%EB%8C%80%EC%83%81-%EC%9D%B4%ED%84%B0%EB%A0%88%EC%9D%B4%EC%85%98-while%EA%B3%BC-for-%EB%A3%A8%ED%94%84\" aria-label=\" 24 대상 이터레이션 while과 for 루프 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>📖 2.4 대상 이터레이션: while과 for 루프</h2>\n<h3 id=\"-241-조건이-참인-동안-코드-반복-while-루프\" style=\"position:relative;\"><a href=\"#-241-%EC%A1%B0%EA%B1%B4%EC%9D%B4-%EC%B0%B8%EC%9D%B8-%EB%8F%99%EC%95%88-%EC%BD%94%EB%93%9C-%EB%B0%98%EB%B3%B5-while-%EB%A3%A8%ED%94%84\" aria-label=\" 241 조건이 참인 동안 코드 반복 while 루프 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>🔖 2.4.1 조건이 참인 동안 코드 반복: while 루프</h3>\n<ul>\n<li>코틀린에는 while과 do-while 루프가 있다.</li>\n<li>내포된 루프의 경우 레이블을 지정할 수 있다.\n<ul>\n<li>break나 continue를 사용할 때 레이블을 참조할 수 있다.</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-242-수에-대해-이터레이션-범위와-순열\" style=\"position:relative;\"><a href=\"#-242-%EC%88%98%EC%97%90-%EB%8C%80%ED%95%B4-%EC%9D%B4%ED%84%B0%EB%A0%88%EC%9D%B4%EC%85%98-%EB%B2%94%EC%9C%84%EC%99%80-%EC%88%9C%EC%97%B4\" aria-label=\" 242 수에 대해 이터레이션 범위와 순열 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>🔖 2.4.2 수에 대해 이터레이션: 범위와 순열</h3>\n<p><code>val oneToTen = 1..10</code></p>\n<ul>\n<li>코틀린에서는 범위를 사용하여 루프를 한다.\n<ul>\n<li>폐구간(양끝 포함)</li>\n<li>두번째 값이 항상 범위에 포함</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun fizzBuzz(i: Int) = when {\n    i % 15 == 0 -&gt; &quot;FizzBuzz&quot;\n    i % 3 == 0 -&gt; &quot;Fizz&quot;\n    i % 5 == 0 -&gt; &quot;Buzz&quot;\n    else -&gt; &quot;$i&quot;\n}\n\nfun main() {\n    for (i in 1..100) {\n        println(fizzBuzz(i))\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>피즈버즈 게임 구현 예시</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    for (i in 100 downTo 1 step 2) {\n        println(fizzBuzz(i))\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>역방향 순열 예시</li>\n<li>반폐구간에 대해 이터레이션 하고 싶다면 ..&#x3C; 연산 사용</li>\n</ul>\n<h3 id=\"-243-맵에-대한-이터레이션\" style=\"position:relative;\"><a href=\"#-243-%EB%A7%B5%EC%97%90-%EB%8C%80%ED%95%9C-%EC%9D%B4%ED%84%B0%EB%A0%88%EC%9D%B4%EC%85%98\" aria-label=\" 243 맵에 대한 이터레이션 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>🔖 2.4.3 맵에 대한 이터레이션</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val collection = listOf(&quot;red&quot;, &quot;green&quot;, &quot;blue&quot;)\n    for (color in collection) {\n        println(&quot;$color &quot;)\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>단순 컬렉션 이터레이션 예시</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val binaryReps = mutableMapOf&lt;Char, String&gt;()\n    for (char in &#39;A&#39;..&#39;F&#39;) {\n        val binary = char.code.toString(radix = 2) // 아스키 코드를 이진 표현으로 변환\n        binaryReps[char] = binary\n    }\n    for ((letter, binary) in binaryReps) {\n        println(&quot;$letter = $binary&quot;)\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>java의 경우 map에 put method를 써야하지만 코틀린은 그렇지 않다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val list = listOf(&quot;10&quot;, &quot;11&quot;, &quot;1001&quot;)\n    for ((index, element) in list.withIndex()) {\n        println(&quot;$index: $element&quot;)\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>index와 함께 컬렉션을 이터레이션 함</li>\n</ul>\n<h3 id=\"-244-in으로-컬렉션이나-범위의-원소-검사\" style=\"position:relative;\"><a href=\"#-244-in%EC%9C%BC%EB%A1%9C-%EC%BB%AC%EB%A0%89%EC%85%98%EC%9D%B4%EB%82%98-%EB%B2%94%EC%9C%84%EC%9D%98-%EC%9B%90%EC%86%8C-%EA%B2%80%EC%82%AC\" aria-label=\" 244 in으로 컬렉션이나 범위의 원소 검사 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>🔖 2.4.4 in으로 컬렉션이나 범위의 원소 검사</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun isLetter(c: Char) = c in &#39;a&#39;..&#39;z&#39; || c in &#39;A&#39;..&#39;Z&#39;\nfun isNotDigit(c: Char) = c !in &#39;0&#39;..&#39;9&#39;</code>\n        </deckgo-highlight-code>\n<ul>\n<li>!in을 사용하면 어떤 값이 범위에 속하지 않는지 검사할 수 있다.</li>\n<li>when에서 in 검사를 사용할 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    println(&quot;Kotlin&quot; in &quot;Java&quot;..&quot;Scala&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>알파벳 순서로 비교하기 때문에 true 반환</li>\n<li>컬렉션도 마찬가지로 in 연산을 사용할 수 있다.</li>\n</ul>\n<h2 id=\"-25-코틀린에서-예외-던지고-잡아내기\" style=\"position:relative;\"><a href=\"#-25-%EC%BD%94%ED%8B%80%EB%A6%B0%EC%97%90%EC%84%9C-%EC%98%88%EC%99%B8-%EB%8D%98%EC%A7%80%EA%B3%A0-%EC%9E%A1%EC%95%84%EB%82%B4%EA%B8%B0\" aria-label=\" 25 코틀린에서 예외 던지고 잡아내기 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>📖 2.5 코틀린에서 예외 던지고 잡아내기</h2>\n<ul>\n<li>자바와 달리 코틀린의 throw는 식이므로 다른 식에 포함될 수 있다.</li>\n</ul>\n<h3 id=\"-251-try-catch-finally를-사용한-예외-처리와-오류-복구\" style=\"position:relative;\"><a href=\"#-251-try-catch-finally%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%9C-%EC%98%88%EC%99%B8-%EC%B2%98%EB%A6%AC%EC%99%80-%EC%98%A4%EB%A5%98-%EB%B3%B5%EA%B5%AC\" aria-label=\" 251 try catch finally를 사용한 예외 처리와 오류 복구 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>🔖 2.5.1 try, catch, finally를 사용한 예외 처리와 오류 복구</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun readNumber(reader: BufferedReader): Int? {\n    try {\n        val line = reader.readLine()\n        return Integer.parseInt(line)\n    } catch (e: NumberFormatException) {\n        return null\n    } finally {\n        reader.close()\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>java와 달리 함수가 던질 수 있는 예외를 명시할 필요가 없다. (throws)</li>\n<li>코틀린은 checked exception과 unchecked exception을 구별하지 앟는다.</li>\n<li>코틀린에서는 컴파일러가 예외 처리를 강제하지 않는다.</li>\n</ul>\n<h3 id=\"-252-try를-식으로-사용\" style=\"position:relative;\"><a href=\"#-252-try%EB%A5%BC-%EC%8B%9D%EC%9C%BC%EB%A1%9C-%EC%82%AC%EC%9A%A9\" aria-label=\" 252 try를 식으로 사용 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>🔖 2.5.2 try를 식으로 사용</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun readNumber(reader: BufferedReader) {\n    val number = try {\n        Integer.parseInt(reader.readLine())\n    } catch (e: NumberFormatException) {\n        return\n    }\n    \n    println(number)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>try의 본문은 반드시 중괄호로 둘러싸야 한다.</li>\n<li>마지막 식의 값이 전체 결과값이다.</li>\n</ul>","excerpt":"📖 2.1 기본 요소: 함수와 변수 🔖 2.1.1 첫 번째 코틀린 프로그램 작성: Hello, World! 함수를 모든 코틀린 파일의 최상위 수준에 정의 가능 main에 인자가 없어도 된다. 간결성 강조 세미콜론(;)을 붙이지 않는 것을 더 권장한다. 🔖 2.1.2 파라미터와 반환값이 있는 함수 선언 파라미터 이름이 먼저 오고 그 뒤에 타입 지정 콜론(:)으로 구분 함수의 반환 타입은 파라미터 목록을 닫는 괄호 다음에 옴. 위와 같은 코드를 블록 본문 함수(block body function…","fields":{"slug":"/backend/kotlin-in-action/2장-코틀린_기초/"},"frontmatter":{"title":"Kotlin in Action - 2장 코틀린 기초","thumbnail":{"childImageSharp":{"fluid":{"src":"/static/f7f7ddfa31d1614405dc5af1487b9ec4/9c94d/kotlin-in-action.png"}}},"draft":false,"category":"Back-End","tags":["Kotlin"],"date":"March 09, 2025"}},"previous":{"id":"f5d54d4a-020c-5fd7-979c-ce466f4ff198","html":"<h2 id=\"-41-클래스-계층-정의\" style=\"position:relative;\"><a href=\"#-41-%ED%81%B4%EB%9E%98%EC%8A%A4-%EA%B3%84%EC%B8%B5-%EC%A0%95%EC%9D%98\" aria-label=\" 41 클래스 계층 정의 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>📖 4.1 클래스 계층 정의</h2>\n<h3 id=\"-411-코틀린-인터페이스\" style=\"position:relative;\"><a href=\"#-411-%EC%BD%94%ED%8B%80%EB%A6%B0-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4\" aria-label=\" 411 코틀린 인터페이스 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>🔖 4.1.1 코틀린 인터페이스</h3>\n<ul>\n<li>코틀린 인터페이스 안에는 추상 메서드뿐 아니라 구현이 있는 메서드도 정의할 수 있다.\n<ul>\n<li>다만, 인터페이스에는 아무런 상태도 들어갈 수 없다.</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface Clickable {\n    fun click()\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Button : Clickable {\n    override fun click() = println(&quot;I was clicked&quot;)\n}\n\nfun main() {\n    Button().click()\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>상속이나 composition에서 모두 클래스 이름 뒤에 콜론을 붙이고 인터페이스나 클래스 이름을 적는 방식을 사용한다.</li>\n<li>클래스는 인터페이스를 원하는 개수 제한 없이 마음대로 구현할 수 있지만 클래스는 오직 하나만 확장할 수 있다.</li>\n<li>오버라이드를 할 때 override 변경자를 꼭 사용해야 한다.\n<ul>\n<li>상위 클래스에 있는 메서드 오버라이딩 방지</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface Clickable {\n    fun click()\n    fun showOff() = println(&quot;I&#39;m clickable!&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>디폴트 구현 가능</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface Focusable {\n    fun setFocus(b: Boolean) = println(&quot;I ${if (b) &quot;got&quot; else &quot;lost&quot;} focus.&quot;)\n    \n    fun showOff() = println(&quot;I&#39;m focusable!&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>한 클래스에서 두 인터페이스를 함께 구현한 후, 동일한 showOff 디폴트 구현을 선택하려면 컴파일러 에러가 발생함.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Button : Clickable, Focusable {\n    override fun click() = println(&quot;I was clicked&quot;)\n    \n    override fun showOff() {\n        super&lt;Clickable&gt;.showOff()\n        super&lt;Focusable&gt;.showOff()\n    }\n}</code>\n        </deckgo-highlight-code>\n<h3 id=\"-412-open-final-abstract-변경자-기본적으로-final\" style=\"position:relative;\"><a href=\"#-412-open-final-abstract-%EB%B3%80%EA%B2%BD%EC%9E%90-%EA%B8%B0%EB%B3%B8%EC%A0%81%EC%9C%BC%EB%A1%9C-final\" aria-label=\" 412 open final abstract 변경자 기본적으로 final 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>🔖 4.1.2 open, final, abstract 변경자: 기본적으로 final</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">open class RichButton : Clickable {\n    fun disable() {}\n    open fun animate() {}\n    override fun click() {}\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>기본적으로 모든 클래스와 메서드는 final이다.\n<ul>\n<li>클래스에 대해 하위 클래스를 만들 수 없고, 기반 클래스의 메서드를 하위 클래스가 오버라이드할 수도 없다.</li>\n</ul>\n</li>\n<li>어떤 클래스의 상속을 허용하려면 open 변경자를 붙여야 한다.\n<ul>\n<li>메서드나 프로퍼티 또한 마찬가지</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">open class RichButton : Clickable {\n    final override fun click() {}\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>명시적으로 오버라이드 금지하려면 final 표시</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">abstract class Animated { // 추상클래스의 인스턴스 만들 수 없음.\n    abstract val animationSpeed: Double // 추상 프로퍼티: 하위 클래스는 반드시 값이나 접근자 제공\n    val keyframes: Int = 20\n    open val frames: Int = 60\n    \n    abstract fun animate() // 추상함수: 하위 클래스는 반드시 오버라이드해야함.\n    open fun stopAnimating() {}\n    fun animateTwice() {}\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>추상클래스는 인스턴스화할 수 없다.</li>\n</ul>\n<h3 id=\"-413-가시성-변경자-기본적으로-공개\" style=\"position:relative;\"><a href=\"#-413-%EA%B0%80%EC%8B%9C%EC%84%B1-%EB%B3%80%EA%B2%BD%EC%9E%90-%EA%B8%B0%EB%B3%B8%EC%A0%81%EC%9C%BC%EB%A1%9C-%EA%B3%B5%EA%B0%9C\" aria-label=\" 413 가시성 변경자 기본적으로 공개 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>🔖 4.1.3 가시성 변경자: 기본적으로 공개</h3>\n<ul>\n<li>가시성 변경자는 코드 기반에 있는 선언에 대한 클래스 외부 접근을 제어</li>\n<li>public, protected, private</li>\n<li>기본적으로 public</li>\n<li>module 안으로만 한정된 가시성을 위해 internal 제공\n<ul>\n<li>module: 함께 컴파일되는 코틀린 파일의 집합</li>\n</ul>\n</li>\n<li>패키지 전용 가시성 개념이 없음</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">internal open class TalkativeButton {\n    private fun yell() = println(&quot;Hey!&quot;)\n    protected fun whisper() = println(&quot;Let&#39;s talk!&quot;)\n}\n\nfun TalkativeButton.giveSpeech() { // 오류\n    yell() // 오류\n    \n    whisper() // 오류\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>기반 타입 목록에 들어있는 타입이나 제네릭 클래스의 타입 파라미터에 들어있는 타입의 가시성은 그 클래스 자신의 가시성과 같거나 더 높아야 하고, 메서드의 시그니처에 사용된 모든 타입의 가시성은 그 메서드의 가시성과 같거나 더 높아야 함.</li>\n<li>클래스를 확장한 함수는 그 클래스의 private이나 protected 멤버에 접근할 수 없다.</li>\n</ul>\n<h3 id=\"-414-내부-클래스와-내포된-클래스-기본적으로-내포-클래스\" style=\"position:relative;\"><a href=\"#-414-%EB%82%B4%EB%B6%80-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%EB%82%B4%ED%8F%AC%EB%90%9C-%ED%81%B4%EB%9E%98%EC%8A%A4-%EA%B8%B0%EB%B3%B8%EC%A0%81%EC%9C%BC%EB%A1%9C-%EB%82%B4%ED%8F%AC-%ED%81%B4%EB%9E%98%EC%8A%A4\" aria-label=\" 414 내부 클래스와 내포된 클래스 기본적으로 내포 클래스 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>🔖 4.1.4 내부 클래스와 내포된 클래스: 기본적으로 내포 클래스</h3>\n<ul>\n<li>자바와 달리 내포 클래스는 명시적으로 요청하지 않는 한 바깥쪽 클래스 인스턴스에 대한 접근 권한이 없다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface State : Serializable\n\ninterface View {\n    fun getCurrentState(): State\n    fun restoreState(state: State) {}\n}\n\nclass Button : View {\n    override fun getCurrentState(): State = ButtonState()\n    override fun restoreState(state: State) {}\n    class ButtonState : State {}\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>내포된 클래스에 아무런 변경자도 없으면 자바 static 내포 클래스와 같다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Outer {\n    inner class Inner {\n        fun getOuterReference(): Outer = this@Outer\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>내부 클래스에서 바깥쪽 클래스의 참조에 접근하려면 this@Outer라고 써야 한다.</li>\n</ul>\n<h3 id=\"-415-봉인된-클래스-확장이-제한된-클래스-계층-정의\" style=\"position:relative;\"><a href=\"#-415-%EB%B4%89%EC%9D%B8%EB%90%9C-%ED%81%B4%EB%9E%98%EC%8A%A4-%ED%99%95%EC%9E%A5%EC%9D%B4-%EC%A0%9C%ED%95%9C%EB%90%9C-%ED%81%B4%EB%9E%98%EC%8A%A4-%EA%B3%84%EC%B8%B5-%EC%A0%95%EC%9D%98\" aria-label=\" 415 봉인된 클래스 확장이 제한된 클래스 계층 정의 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>🔖 4.1.5 봉인된 클래스: 확장이 제한된 클래스 계층 정의</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface Expr\nclass Num(val value: Int) : Expr\nclass Sum(val left: Expr, val right: Expr) : Expr\n\nfun eval(e: Expr): Int =\n    when (e) {\n        is Num -&gt; e.value\n        is Sum -&gt; eval(e.left) + eval(e.right)\n        else -&gt; throw IllegalArgumentException(&quot;Unknown expression&quot;)\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>when을 사용할 때 else는 강제이다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">sealed class Expr\nclass Num(val value: Int) : Expr()\nclass Sum(val left: Expr, val right: Expr) : Expr()\n\nfun eval(e: Expr): Int =\n    when (e) {\n        is Num -&gt; e.value\n        is Sum -&gt; eval(e.left) + eval(e.right)\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>sealed 변경자를 붙이면 그 상위 클래스를 상속한 하위 클래스의 가능성을 제한할 수 있다.</li>\n<li>하위 클래스들은 반드시 컴파일 시점에 알려져야 하며, sealed 클래스가 정의된 패키지와 같은 패키지에 속해야 하며, 모든 하위클래스가 같은 모듈 안에 위치해야 한다.</li>\n<li>디폴트 분기(else)가 필요 없다.</li>\n<li>sealed 변경자는 클래스가 추상 클래스임을 명시한다.\n<ul>\n<li>abstract를 붙일 필요가 없음.</li>\n<li>추상 멤버를 선언한 수 있음.</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">sealed interface Toggleable {\n    fun toggle()\n}\n\nclass LightSwitch : Toggleable {\n    override fun toggle() = println(&quot;Lights!&quot;)\n}\n\nclass Camera: Toggleable {\n    override fun toggle() = println(&quot;Camera!&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>봉인된 인터페이스도 똑같은 규칙을 따름.</li>\n<li>봉인된 인터페이스가 속한 모듈이 컴파일되고 나면 이 인터페이스에 대한 새로운 구현을 밖에서 추가할 수 없다.</li>\n</ul>\n<h2 id=\"-42-뻔하지-않은-생성자나-프로퍼티를-갖는-클래스-선언\" style=\"position:relative;\"><a href=\"#-42-%EB%BB%94%ED%95%98%EC%A7%80-%EC%95%8A%EC%9D%80-%EC%83%9D%EC%84%B1%EC%9E%90%EB%82%98-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0%EB%A5%BC-%EA%B0%96%EB%8A%94-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%84%A0%EC%96%B8\" aria-label=\" 42 뻔하지 않은 생성자나 프로퍼티를 갖는 클래스 선언 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>📖 4.2 뻔하지 않은 생성자나 프로퍼티를 갖는 클래스 선언</h2>\n<h3 id=\"-421-클래스-초기화-주-생성자와-초기화-블록\" style=\"position:relative;\"><a href=\"#-421-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%B4%88%EA%B8%B0%ED%99%94-%EC%A3%BC-%EC%83%9D%EC%84%B1%EC%9E%90%EC%99%80-%EC%B4%88%EA%B8%B0%ED%99%94-%EB%B8%94%EB%A1%9D\" aria-label=\" 421 클래스 초기화 주 생성자와 초기화 블록 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>🔖 4.2.1 클래스 초기화: 주 생성자와 초기화 블록</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class User(val nickname: String)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>클래스 이름 뒤에 오는 괄호로 둘러쌓인 코드를 <strong>주 생성자</strong>라고 부른다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class User constructor(_nickname: String) {\n    val nickname: String\n    \n    init {\n        nickname = _nickname\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>constructor 키워드는 주 생성자나 부 생성자 정의를 시작할 때 사용한다.</li>\n<li>init 키워드는 초기화 블록을 시작한다.</li>\n<li>주 생성자 앞에 별다른 어노테이션이나 가시성 변경자가 없다면 constructor를 생략해도 된다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class User(val nickname: String, val isSubscribed: Boolean = true)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>생성자 파라미터에도 기본값을 정의할 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">open class User(val nickname: String)\n\nclass SocialUser(nickname: String) : User(nickname)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>기반 클래스의 생성자가 인자를 받아야 한다면 클래스의 주 생성자에서 기반 생성자를 호출해야 할 필요가 있다.</li>\n<li>클래스를 정의할 때 별도로 생성자를 정의하지 않으면 컴파일러가 자동으로 인자가 없는 디폴트 생성자를 만들어준다.\n<ul>\n<li>기반 클래스의 이름 뒤에 빈 괄호 필요</li>\n<li>인터페이스의 경우 생성자가 없으므로 괄호가 없음.</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Secretive private constructor(private val agentName: String) {}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>클래스 외부에서 인스턴스화하지 못하게 막고 싶다면 private 선언</li>\n</ul>\n<h3 id=\"-422-부-생성자-상위-클래스를-다른-방식으로-초기화\" style=\"position:relative;\"><a href=\"#-422-%EB%B6%80-%EC%83%9D%EC%84%B1%EC%9E%90-%EC%83%81%EC%9C%84-%ED%81%B4%EB%9E%98%EC%8A%A4%EB%A5%BC-%EB%8B%A4%EB%A5%B8-%EB%B0%A9%EC%8B%9D%EC%9C%BC%EB%A1%9C-%EC%B4%88%EA%B8%B0%ED%99%94\" aria-label=\" 422 부 생성자 상위 클래스를 다른 방식으로 초기화 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>🔖 4.2.2 부 생성자: 상위 클래스를 다른 방식으로 초기화</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">open class Downloader {\n    constructor(url: String?) {}\n    \n    constructor(uri: URI?) {}\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린은 코틀린의 디폴트 파라미터 값과 이름 붙은 인자 문법을 사용하므로 부생성자가 필요할 일이 적다.</li>\n<li>상위 클래스에서 super() 키워드를 통해 자신에 대응하는 상위 클래스 생성자를 호출한다.</li>\n<li>this()를 통해 클래스 자신의 다른 생성자를 호출할 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class MyDownloader : Downloader() {\n    constructor(url: String?) : this(URI(url))\n    constructor(uri: URI?) : super(uri)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>클래스에 주 생성자가 없다면 모든 부 생성자는 반드시 상위 클래스를 초기화하거나 다른 생성자에게 생성을 위임해야 한다.</li>\n<li>부 생성자가 필요한 주된 이유는 자바 상호운영성이다.</li>\n</ul>\n<h3 id=\"-423-인터페이스에-선언된-프로퍼티-구현\" style=\"position:relative;\"><a href=\"#-423-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4%EC%97%90-%EC%84%A0%EC%96%B8%EB%90%9C-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0-%EA%B5%AC%ED%98%84\" aria-label=\" 423 인터페이스에 선언된 프로퍼티 구현 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>🔖 4.2.3 인터페이스에 선언된 프로퍼티 구현</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface User {\n    val nickname: String\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>인터페이스에 추상 프로퍼티 선언을 넣을 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class PrivateUser(override val nickname: String) : User\n\nclass SubscribingUser(val email: String) : User {\n    override val nickname: String\n        get() = email.substringBefore(&#39;@&#39;)\n}\n\nclass SocialUser(val accountId: Int) : User {\n    override val nickname: getFacebookName(accountId)\n}\n\nfun getNameFromSocialNetwork(accountId: Int) = &quot;bottleh$accountId&quot;</code>\n        </deckgo-highlight-code>\n<ul>\n<li>인터페이스의 프로퍼티 구현하기</li>\n<li>인터페이스에 추상 프로퍼티뿐 아니라 게터와 세터가 있는 프로퍼티를 선언할 수도 있다.\n<ul>\n<li>위와 같은 게터와 세터는 뒷받침하는 필드를 참조할 수 없다.</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface EmailUser {\n    val email: String\n    val nickname: String\n        get() = email.substringBefore(&#39;@&#39;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>하위 클래스는 email을 반드시 오버라이딩</li>\n<li>nickname 상속 가능</li>\n</ul>\n<h4 id=\"️-함수-대신-프로퍼티를-사용할-때\" style=\"position:relative;\"><a href=\"#%EF%B8%8F-%ED%95%A8%EC%88%98-%EB%8C%80%EC%8B%A0-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%A0-%EB%95%8C\" 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<ul>\n<li>예외를 던지지 않는다.</li>\n<li>계산 비용이 적게 든다.</li>\n<li>객체 상태가 바뀌지 않으면 여러 번 호출해도 항상 같은 결과를 돌려준다.</li>\n</ul>\n<h3 id=\"-424-게터와-세터에서-뒷받침하는-필드에-접근\" style=\"position:relative;\"><a href=\"#-424-%EA%B2%8C%ED%84%B0%EC%99%80-%EC%84%B8%ED%84%B0%EC%97%90%EC%84%9C-%EB%92%B7%EB%B0%9B%EC%B9%A8%ED%95%98%EB%8A%94-%ED%95%84%EB%93%9C%EC%97%90-%EC%A0%91%EA%B7%BC\" aria-label=\" 424 게터와 세터에서 뒷받침하는 필드에 접근 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>🔖 4.2.4 게터와 세터에서 뒷받침하는 필드에 접근</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class User(val name: String) {\n    var address: String = &quot;unspecified&quot;\n    set(value: String) {\n        println(\n            &quot;&quot;&quot;\n                Address was changed for $name:\n                &quot;$field&quot; -&gt; &quot;$value&quot;.\n            &quot;&quot;&quot;.trimIndent())\n        field = value\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>세터에서 뒷받침하는 필드 접근</li>\n<li>접근자의 본문에서는 field라는 특별한 식별자를 통해 뒷받침하는 필드에 접근할 수 있다.</li>\n<li>var인 경우에는 게터나 세터 모두에 field가 없어야 한다.</li>\n</ul>\n<h3 id=\"-425-접근자의-가시성-변경\" style=\"position:relative;\"><a href=\"#-425-%EC%A0%91%EA%B7%BC%EC%9E%90%EC%9D%98-%EA%B0%80%EC%8B%9C%EC%84%B1-%EB%B3%80%EA%B2%BD\" aria-label=\" 425 접근자의 가시성 변경 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>🔖 4.2.5 접근자의 가시성 변경</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class LengthCounter {\n    var counter: Int = 0\n        private set // 클래스 밖에서 이 프로퍼티의 값을 바꿀 수 없다.\n\n    fun addWord(word: String) {\n        counter += word.length\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>클래스 외부에서 이 프로퍼티에 값을 쓰려하면 컴파일 시점 오류가 발생</li>\n</ul>\n<h2 id=\"-43-컴파일러가-생성한-메서드-데이터-클래스와-클래스-위임\" style=\"position:relative;\"><a href=\"#-43-%EC%BB%B4%ED%8C%8C%EC%9D%BC%EB%9F%AC%EA%B0%80-%EC%83%9D%EC%84%B1%ED%95%9C-%EB%A9%94%EC%84%9C%EB%93%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%9C%84%EC%9E%84\" aria-label=\" 43 컴파일러가 생성한 메서드 데이터 클래스와 클래스 위임 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>📖 4.3 컴파일러가 생성한 메서드: 데이터 클래스와 클래스 위임</h2>\n<h3 id=\"-431-모든-클래스가-정의해야-하는-메서드\" style=\"position:relative;\"><a href=\"#-431-%EB%AA%A8%EB%93%A0-%ED%81%B4%EB%9E%98%EC%8A%A4%EA%B0%80-%EC%A0%95%EC%9D%98%ED%95%B4%EC%95%BC-%ED%95%98%EB%8A%94-%EB%A9%94%EC%84%9C%EB%93%9C\" aria-label=\" 431 모든 클래스가 정의해야 하는 메서드 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>🔖 4.3.1 모든 클래스가 정의해야 하는 메서드</h3>\n<deckgo-highlight-code language=\"kotilin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Customer(val name: String, val postalCode: Int)</code>\n        </deckgo-highlight-code>\n<h4 id=\"️-문자열-표현-tostring\" style=\"position:relative;\"><a href=\"#%EF%B8%8F-%EB%AC%B8%EC%9E%90%EC%97%B4-%ED%91%9C%ED%98%84-tostring\" aria-label=\"️ 문자열 표현 tostring 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>🛠️ 문자열 표현: toString()</h4>\n<ul>\n<li>기본 제공되는 객체의 문자열 표현은 클래스 이름과 객체의 주소를 표현함.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Customer(val name: String, val postalCode: Int) {\n    override fun toString() = &quot;Customer(name=$name, postalCode=$postalCode)&quot;\n}</code>\n        </deckgo-highlight-code>\n<h4 id=\"️-객체의-동등성-equals\" style=\"position:relative;\"><a href=\"#%EF%B8%8F-%EA%B0%9D%EC%B2%B4%EC%9D%98-%EB%8F%99%EB%93%B1%EC%84%B1-equals\" aria-label=\"️ 객체의 동등성 equals 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>🛠️ 객체의 동등성: equals()</h4>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Customer(val name: String, val postalCode: Int) {\n    override fun equals(other: Any?): Boolean {\n        if (other == null || other !is Customer) \n            return false\n        return name == other.name &amp;&amp; postalCode == other.postalCode\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린에서 == 연산자는 참조 동일성을 검사하지 않고 객체의 동등성을 검사한다.</li>\n<li>Any는 Java의 Object에 대응되는 모든 클래스의 최상위 클래스</li>\n</ul>\n<h4 id=\"️-해시-컨테이너-hashcode\" style=\"position:relative;\"><a href=\"#%EF%B8%8F-%ED%95%B4%EC%8B%9C-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-hashcode\" aria-label=\"️ 해시 컨테이너 hashcode 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>🛠️ 해시 컨테이너: hashCode()</h4>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Customer(val name: String, val postalCode: Int) {\n    override fun equals(other: Any?): Boolean {\n        if (other == null || other !is Customer)\n            return false\n        return name == other.name &amp;&amp; postalCode == other.postalCode\n    }\n    override fun hashCode(): Int = name.hashCode() * 31 + postalCode\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>JVM 언어에서는 hashCode가 지켜야 하는 equals()가 true를 반환하는 두 객체는 반드시 같은 hasCode()를 반환해야 한다.</li>\n</ul>\n<h3 id=\"-432-데이터-클래스-모든-클래스가-정의해야-하는-메서드를-자동으로-생성\" style=\"position:relative;\"><a href=\"#-432-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%81%B4%EB%9E%98%EC%8A%A4-%EB%AA%A8%EB%93%A0-%ED%81%B4%EB%9E%98%EC%8A%A4%EA%B0%80-%EC%A0%95%EC%9D%98%ED%95%B4%EC%95%BC-%ED%95%98%EB%8A%94-%EB%A9%94%EC%84%9C%EB%93%9C%EB%A5%BC-%EC%9E%90%EB%8F%99%EC%9C%BC%EB%A1%9C-%EC%83%9D%EC%84%B1\" aria-label=\" 432 데이터 클래스 모든 클래스가 정의해야 하는 메서드를 자동으로 생성 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>🔖 4.3.2 데이터 클래스: 모든 클래스가 정의해야 하는 메서드를 자동으로 생성</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">data class Customer(val name: String, val postalCode: Int)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>equals, hasCode, toString을 모두 포함한다.</li>\n</ul>\n<h4 id=\"️-데이터-클래스와-불변성-copy-메서드\" style=\"position:relative;\"><a href=\"#%EF%B8%8F-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%EB%B6%88%EB%B3%80%EC%84%B1-copy-%EB%A9%94%EC%84%9C%EB%93%9C\" aria-label=\"️ 데이터 클래스와 불변성 copy 메서드 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>🛠️ 데이터 클래스와 불변성: copy() 메서드</h4>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Customer(val name: String, val postalCode: Int) {\n    fun copy(name: String = this.name, postalCode: Int = this.postalCode): Customer = Customer(name, postalCode)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>불변 객체를 사용하면 프로그램에 대해 훨씬 쉽게 추론할 수 있다.</li>\n<li>데이터 클래스는 copy 메서드를 제공한다.\n<ul>\n<li>객체를 복사하면서 일부 프로퍼티를 바꿀 수 있게 해주는 copy 메서드</li>\n</ul>\n</li>\n</ul>\n<h4 id=\"️-클래스-위임-by-키워드-사용\" style=\"position:relative;\"><a href=\"#%EF%B8%8F-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%9C%84%EC%9E%84-by-%ED%82%A4%EC%9B%8C%EB%93%9C-%EC%82%AC%EC%9A%A9\" aria-label=\"️ 클래스 위임 by 키워드 사용 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>🛠️ 클래스 위임: by 키워드 사용</h4>\n<p>Decorator 패턴</p>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class DelegatingCollection&lt;T&gt;: Collection&lt;T&gt; {\n    private val innerList = arrayListOf&lt;T&gt;()\n    \n    override val size: Int get() = innerList.size\n    override fun isEmpty(): Boolean = innerList.isEmpty()\n    override fun contains(element: T): Boolean = innerList.contains(element)\n    override fun containsAll(elements: Collection&lt;T&gt;): Boolean = innerList.containsAll(elements)\n    override fun iterator(): Iterator&lt;T&gt; = innerList.iterator()\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class DelegatingCollection&lt;T&gt;(innerList: Collection&lt;T&gt; = mutableListOf&lt;T&gt;()) : Collection&lt;T&gt; by innerList</code>\n        </deckgo-highlight-code>\n<ul>\n<li>상속을 허용하지 않는 클래스에게 새로운 동작을 추가해야 할 때 쓰는 방법</li>\n<li>기존 클래스 대신 사용할 수 있는 데코레이터(새로운 클래스)를 만들되, 기존 클래스와 같은 인터페이스를 데코레이터가 제공하고 기존 클래스를 데코레이터 내부 필드로 유지하는 것</li>\n<li>새로 정의해야 하는 기능은 데코레이터의 메서드로 새로 정의</li>\n<li>기존 기능이 그대로 필요한 부분은 데코레이터의 메서드가 기존 클래스의 메서드에게 요청을 전달</li>\n<li>단점: 준비 코드가 상당히 많이 필요함.</li>\n<li>코틀린은 by 키워드를 통해 제공함.</li>\n</ul>\n<h2 id=\"-44-object-키워드-클래스-선언과-인스턴스-생성을-한꺼번에-하기\" style=\"position:relative;\"><a href=\"#-44-object-%ED%82%A4%EC%9B%8C%EB%93%9C-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%84%A0%EC%96%B8%EA%B3%BC-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%EC%83%9D%EC%84%B1%EC%9D%84-%ED%95%9C%EA%BA%BC%EB%B2%88%EC%97%90-%ED%95%98%EA%B8%B0\" aria-label=\" 44 object 키워드 클래스 선언과 인스턴스 생성을 한꺼번에 하기 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>📖 4.4 object 키워드: 클래스 선언과 인스턴스 생성을 한꺼번에 하기</h2>\n<p>object 키워드를 쓰는 상황</p>\n<ul>\n<li>객체 선언</li>\n<li>동반 객체</li>\n<li>객체 식\n<ul>\n<li>자바의 익명 내부 클래스</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-441-객체-선언-싱글턴을-쉽게-만들기\" style=\"position:relative;\"><a href=\"#-441-%EA%B0%9D%EC%B2%B4-%EC%84%A0%EC%96%B8-%EC%8B%B1%EA%B8%80%ED%84%B4%EC%9D%84-%EC%89%BD%EA%B2%8C-%EB%A7%8C%EB%93%A4%EA%B8%B0\" aria-label=\" 441 객체 선언 싱글턴을 쉽게 만들기 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>🔖 4.4.1 객체 선언: 싱글턴을 쉽게 만들기</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">object Payroll {\n    val allEmployees = arrayListOf&lt;Person&gt;()\n    \n    fun calculateSalary() {\n        for (person in allEmployees) {\n            \n        }\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>객체 선언은 object 키워드로 시작</li>\n<li>객체 선언은 클래스를 정의하고 그 클래스의 인스턴스를 만들어 변수에 저장하는 모든 작업을 한 문장으로 처리</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">object CaseInsensitiveFileComparator : Comparator&lt;File&gt; {\n    override fun compare(file1: File, file2: File): Int {\n        return file1.path.compareTo(file2.path, ignoreCase = true)\n    }\n}\n\nfun main() {\n    println(\n        CaseInsensitiveFileComparator.compare(\n            File(&quot;/User&quot;), File(&quot;/user&quot;)\n        )\n    )\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>일반 객체(클래스 인스턴스)를 사용할 수 있는 곳에서는 항상 싱글턴 객체를 사용할 수 있다.</li>\n</ul>\n<h3 id=\"-442-동반-객체-팩토리-메서드와-정적-멤버가-들어갈-장소\" style=\"position:relative;\"><a href=\"#-442-%EB%8F%99%EB%B0%98-%EA%B0%9D%EC%B2%B4-%ED%8C%A9%ED%86%A0%EB%A6%AC-%EB%A9%94%EC%84%9C%EB%93%9C%EC%99%80-%EC%A0%95%EC%A0%81-%EB%A9%A4%EB%B2%84%EA%B0%80-%EB%93%A4%EC%96%B4%EA%B0%88-%EC%9E%A5%EC%86%8C\" aria-label=\" 442 동반 객체 팩토리 메서드와 정적 멤버가 들어갈 장소 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>🔖 4.4.2 동반 객체: 팩토리 메서드와 정적 멤버가 들어갈 장소</h3>\n<ul>\n<li>코틀린 클래스 안에는 정적인 멤버가 없다.\n<ul>\n<li>패키지 수준의 최상위 함수와 객체 선언을 활용</li>\n<li>대부분 최상위 함수를 활용하는 편을 더 권장한다.</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class MyClass {\n    companion object {\n        fun callMe() {\n            println(&quot;Companion object called&quot;)\n        }\n    }\n}\n\nfun main() {\n    MyClass.callMe()\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>클래스 안에 정의된 객체 중 하나에 companion이라는 특별한 표시를 붙일 수 있다.</li>\n<li>객체 멤버에 접근할 때 자신을 감싸는 클래스의 이름을 통해 직접 사용할 수 있게 된다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val myObject = MyClass()\n    myObject.callMe() // error\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>해당 클래스의 인스턴스는 동반 객체의 멤버에 접근할 수 없다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class User {\n    val nickname: String\n    \n    constructor(email: String) {\n        nickname = email.substringBefore(&#39;@&#39;)\n    }\n    \n    constructor(socialAccountId: Int) {\n        nickname = getSocialNetworkName(socialAccountId)\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class User private constructor(val nickname: String) {\n    companion object {\n        fun newSubscribingUser(email: String) = User(email.substringBefore(&#39;@&#39;))\n        fun newSocialUser(accountId: Int) = User(getNameFromSocialNetwork(accountId))\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>동반 객체가 private 생성자를 호출하기 좋은 위치다.</li>\n<li>바깥쪽 클래스의 private 생성자도 호출할 수 있다.</li>\n<li>즉, 팩토리 패턴을 구현하기 가장 적합한 위치가 될 수 있다.</li>\n<li>팩토리 메서드는 그 팩토리 메서드가 선언된 클래스의 하위 클래스 객체를 반환할 수도 있다.</li>\n</ul>\n<h3 id=\"-443-동반-객체를-일반-객체처럼-사용\" style=\"position:relative;\"><a href=\"#-443-%EB%8F%99%EB%B0%98-%EA%B0%9D%EC%B2%B4%EB%A5%BC-%EC%9D%BC%EB%B0%98-%EA%B0%9D%EC%B2%B4%EC%B2%98%EB%9F%BC-%EC%82%AC%EC%9A%A9\" aria-label=\" 443 동반 객체를 일반 객체처럼 사용 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>🔖 4.4.3 동반 객체를 일반 객체처럼 사용</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Person(val name: String) {\n    companion object Loader {\n        fun fromJSON(jsonText: String): Person = /* */\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>필요하다면 동반객체에 이름을 붙일 수 있다.</li>\n</ul>\n<h4 id=\"️-동반-객체에서-인터페이스-구현\" style=\"position:relative;\"><a href=\"#%EF%B8%8F-%EB%8F%99%EB%B0%98-%EA%B0%9D%EC%B2%B4%EC%97%90%EC%84%9C-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EA%B5%AC%ED%98%84\" 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=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface JSONFactory&lt;T&gt; {\n    fun fromJSON(jsonText: String): T\n}\n\nclass Person(val name: String) {\n    companion object : JSONFactory&lt;Person&gt; {\n        override fun fromJSON(jsonText: String): Person = /* */\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>동반 객체도 인터페이스를 구현할 수 있다.</li>\n</ul>\n<h4 id=\"️-동반-객체-확장\" style=\"position:relative;\"><a href=\"#%EF%B8%8F-%EB%8F%99%EB%B0%98-%EA%B0%9D%EC%B2%B4-%ED%99%95%EC%9E%A5\" 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=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Person(val firstName: String, val lastName: String) {\n    companion object {\n    }\n}\n\nfun Person.Companion.fromJSON(json: String): Person {\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>마치 동반 객체 안에서 <code>fromJSON</code> 함수를 정의한 것처럼 호출할 수 있다.</li>\n<li>동반 객체에 대한 확장 함수를 작성할 수 있으려면 원래 클래스에 동반 객체를 꼭 선언해야 한다.</li>\n</ul>\n<h3 id=\"-444-객체-식-익명-내부-클래스를-다른-방식으로-작성\" style=\"position:relative;\"><a href=\"#-444-%EA%B0%9D%EC%B2%B4-%EC%8B%9D-%EC%9D%B5%EB%AA%85-%EB%82%B4%EB%B6%80-%ED%81%B4%EB%9E%98%EC%8A%A4%EB%A5%BC-%EB%8B%A4%EB%A5%B8-%EB%B0%A9%EC%8B%9D%EC%9C%BC%EB%A1%9C-%EC%9E%91%EC%84%B1\" aria-label=\" 444 객체 식 익명 내부 클래스를 다른 방식으로 작성 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>🔖 4.4.4 객체 식: 익명 내부 클래스를 다른 방식으로 작성</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface MouseListener {\n    fun onEnter()\n    fun onClick()\n}\n\nclass Button(private val listener: MouseListener) {\n    \n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    Button(object : MouseListener {\n        override fun onEnter() {}\n        override fun onClick() {}\n    })\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>객체 식을 사용해 익명 객체를 만든다.</li>\n<li>객체 선언과 같지만 이름이 빠졌다.</li>\n<li>객체 식은 익명 객체 안에서 여러 메서드를 오버라이드해야 하는 경우에 훨씬 더 유용하다.</li>\n</ul>\n<h2 id=\"-45-부가-비용-없이-타입-안전성-추가-인라인-클래스\" style=\"position:relative;\"><a href=\"#-45-%EB%B6%80%EA%B0%80-%EB%B9%84%EC%9A%A9-%EC%97%86%EC%9D%B4-%ED%83%80%EC%9E%85-%EC%95%88%EC%A0%84%EC%84%B1-%EC%B6%94%EA%B0%80-%EC%9D%B8%EB%9D%BC%EC%9D%B8-%ED%81%B4%EB%9E%98%EC%8A%A4\" aria-label=\" 45 부가 비용 없이 타입 안전성 추가 인라인 클래스 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>📖 4.5 부가 비용 없이 타입 안전성 추가: 인라인 클래스</h2>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun addExpense(expense: Int) {\n    // 비용을 미국 달러의 센트 단위로 저장\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>200엔 지출을 추가하려면 Int 타입으로만 받기 때문에 다른 의미의 값을 전달하는 것을 막을 수 없다.</li>\n<li>전형적인 해법은 Int 대신 Class를 사용하는 것</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class UsdCent(val amount: Int)\n\nfun addExpense(expense: UsdCent) {\n    // 비용을 미국 달러의 센트 단위로 저장\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>위와 같이 구현하면 GC 비용이 증가하게 된다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@JvmInline\nvalue class UsdCent(val amount: Int)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>인라인 클래스를 사용하면 성능을 희생하지 않고 타입 안정성을 얻을 수 있다.</li>\n<li>실행 시점에 UsdCent의 인스턴스는 감싸진 프로퍼티로 대체된다.</li>\n<li>인라인으로 표시하려면 클래스가 프로퍼티를 하나만 가져야 하며, 그 프로퍼티는 주 생성자에서 초기화돼야 한다.</li>\n<li>인라인 클래스는 클래스 계층에 참여하지 않는다.\n<ul>\n<li>다른 클래스를 상속할 수도, 다른 클래스가 상속할 수도 없음.</li>\n<li>인터페이스 상속, 메서드 정의, 계산된 프로퍼티를 제공</li>\n</ul>\n</li>\n</ul>","excerpt":"📖 4.1 클래스 계층 정의 🔖 4.1.1 코틀린 인터페이스 코틀린 인터페이스 안에는 추상 메서드뿐 아니라 구현이 있는 메서드도 정의할 수 있다. 다만, 인터페이스에는 아무런 상태도 들어갈 수 없다. 상속이나 composition에서 모두 클래스 이름 뒤에 콜론을 붙이고 인터페이스나 클래스 이름을 적는 방식을 사용한다. 클래스는 인터페이스를 원하는 개수 제한 없이 마음대로 구현할 수 있지만 클래스는 오직 하나만 확장할 수 있다. 오버라이드를 할 때 override…","fields":{"slug":"/backend/kotlin-in-action/4장-클래스_객체_인터페이스/"},"frontmatter":{"title":"Kotlin in Action - 4장 클래스, 객체, 인터페이스","thumbnail":{"childImageSharp":{"fluid":{"src":"/static/f7f7ddfa31d1614405dc5af1487b9ec4/9c94d/kotlin-in-action.png"}}},"draft":false,"category":"Back-End","tags":["Kotlin"],"date":"March 23, 2025"}},"node":{"id":"f3c5a39a-dd42-5db5-849f-06d2ef7e0de0","html":"<h2 id=\"-31-코틀린에서-컬렉션-만들기\" style=\"position:relative;\"><a href=\"#-31-%EC%BD%94%ED%8B%80%EB%A6%B0%EC%97%90%EC%84%9C-%EC%BB%AC%EB%A0%89%EC%85%98-%EB%A7%8C%EB%93%A4%EA%B8%B0\" aria-label=\" 31 코틀린에서 컬렉션 만들기 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>📖 3.1 코틀린에서 컬렉션 만들기</h2>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    fun main() {\n        val set = setOf(1, 7, 53)\n        val list = listOf(1, 7, 53)\n        val map = mapOf(1 to &quot;one&quot;, 7 to &quot;seven&quot;, 53 to &quot;fifty-three&quot;)\n        \n        println(set.javaClass)\n        println(list.javaClass)\n        println(map.javaClass)\n    }</code>\n        </deckgo-highlight-code>\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<h2 id=\"-32-함수를-호출하기-쉽게-만들기\" style=\"position:relative;\"><a href=\"#-32-%ED%95%A8%EC%88%98%EB%A5%BC-%ED%98%B8%EC%B6%9C%ED%95%98%EA%B8%B0-%EC%89%BD%EA%B2%8C-%EB%A7%8C%EB%93%A4%EA%B8%B0\" aria-label=\" 32 함수를 호출하기 쉽게 만들기 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>📖 3.2 함수를 호출하기 쉽게 만들기</h2>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    fun &lt;T&gt; joinToString(\n        collection: Collection&lt;T&gt;,\n        separator: String,\n        prefix: String,\n        postfix: String\n    ): String {\n        \n        val result = StringBuilder(prefix)\n        \n        for ((index, element) in collection.withIndex()) {\n            if (index &gt; 0) result.append(separator) // 첫 원소 앞에는 구분자를 붙이면 안된다.\n            result.append(element)\n        }\n        \n        result.append(postfix)\n        return result.toString()\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>덜 번잡하게 만들 수는 없을까?</li>\n</ul>\n<h3 id=\"-321-이름-붙인-인자\" style=\"position:relative;\"><a href=\"#-321-%EC%9D%B4%EB%A6%84-%EB%B6%99%EC%9D%B8-%EC%9D%B8%EC%9E%90\" aria-label=\" 321 이름 붙인 인자 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>🔖 3.2.1 이름 붙인 인자</h3>\n<p>자바의 일부 코딩스타일에서는 method 호출 시, 파라미터 이름을 주석에 넣으라고 요구하기도 한다.</p>\n<ul>\n<li>코틀린으로 작성한 함수를 호출할 때는 함수에 전달하는 인자 중 일부(또는 전부)의 이름을 명시할 수 있다.\n<ul>\n<li>모든 인자의 이름을 지정한다면 인자 순서도 변경 가능하다!</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-322-디폴트-파라미터-값\" style=\"position:relative;\"><a href=\"#-322-%EB%94%94%ED%8F%B4%ED%8A%B8-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0-%EA%B0%92\" aria-label=\" 322 디폴트 파라미터 값 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>🔖 3.2.2 디폴트 파라미터 값</h3>\n<p>자바에서는 일부 클래스에서 오버로딩한 메서드가 너무 많아질 수 있다.</p>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    fun &lt;T&gt; joinToString(\n        collection: Collection&lt;T&gt;,\n        separator: String = &quot;, &quot;,\n        prefix: String = &quot;&quot;,\n        postfix: String = &quot;&quot;\n    ): String</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린에서는 함수 선언에서 파라미터의 기본값을 지정할 수 있어, 오버로딩을 상당히 피할 수 있다.</li>\n<li>함수의 디폴트 파라미터 값은 함수를 호출하는 쪽이 아니라 함수 선언쪽에 인코딩된다.</li>\n</ul>\n<h3 id=\"-323-정적인-유틸리티-클래스-없애기-최상위-함수와-프로퍼티\" style=\"position:relative;\"><a href=\"#-323-%EC%A0%95%EC%A0%81%EC%9D%B8-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%97%86%EC%95%A0%EA%B8%B0-%EC%B5%9C%EC%83%81%EC%9C%84-%ED%95%A8%EC%88%98%EC%99%80-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0\" aria-label=\" 323 정적인 유틸리티 클래스 없애기 최상위 함수와 프로퍼티 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>🔖 3.2.3 정적인 유틸리티 클래스 없애기: 최상위 함수와 프로퍼티</h3>\n<ul>\n<li>코틀린에서는 함수를 모든 다른 클래스의 밖에 위치시키면 된다.\n<ul>\n<li>함수들은 여전히 그 파일의 맨 앞에 정의된 패키지의 멤버 함수이므로 다른 패키지에서 그 함수를 사용하고 싶을 때는 그 함수가 정의된 패키지를 임포트해야만 한다.</li>\n<li>클래스이름을 내포하지 않아도 된다.</li>\n</ul>\n</li>\n<li>코틀린 컴파일러가 생성하는 클래스의 이름이 최상위 함수가 들어있던 코틀린 소스파일의 이름과 대응한다.\n<ul>\n<li><code>join.kt</code> -> <code>JoinKt</code></li>\n</ul>\n</li>\n</ul>\n<h4 id=\"최상위-프로퍼티\" style=\"position:relative;\"><a href=\"#%EC%B5%9C%EC%83%81%EC%9C%84-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0\" 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<ul>\n<li>함수와 마찬가지로 프로퍼티도 파일 최상위 수준에 놓을 수 있다.</li>\n<li>상수와 변수 모두 설정가능하다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">var opCount = 0\nval UNIX_LINE_SEPARATOR = &quot;\\n&quot;\nconst val UNIX_LINE_SEPARATOR = &quot;\\n&quot; // java code에 public static final 필드로 노출하고 싶다면 const 변경자 추가</code>\n        </deckgo-highlight-code>\n<h2 id=\"-33-메서드를-다른-클래스에-추가-확장-함수와-확장-프로퍼티\" style=\"position:relative;\"><a href=\"#-33-%EB%A9%94%EC%84%9C%EB%93%9C%EB%A5%BC-%EB%8B%A4%EB%A5%B8-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%97%90-%EC%B6%94%EA%B0%80-%ED%99%95%EC%9E%A5-%ED%95%A8%EC%88%98%EC%99%80-%ED%99%95%EC%9E%A5-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0\" aria-label=\" 33 메서드를 다른 클래스에 추가 확장 함수와 확장 프로퍼티 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>📖 3.3 메서드를 다른 클래스에 추가: 확장 함수와 확장 프로퍼티</h2>\n<p>확장 함수</p>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun String.lastChar(): Char = this.get(this.length - 1)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>어떤 클래스의 멤버 메서드인 것처럼 호출할 수 있지만 그 클래스 밖에 선언된 함수</li>\n<li>수신 객체 타입: 확장이 정의될 클래스의 타입</li>\n<li>수신 객체: 호출하는 대상 값(객체)</li>\n</ul>\n<h3 id=\"-331-임포트와-확장-함수\" style=\"position:relative;\"><a href=\"#-331-%EC%9E%84%ED%8F%AC%ED%8A%B8%EC%99%80-%ED%99%95%EC%9E%A5-%ED%95%A8%EC%88%98\" aria-label=\" 331 임포트와 확장 함수 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>🔖 3.3.1 임포트와 확장 함수</h3>\n<ul>\n<li>확장 함수를 쓰려면 다른 클래스나 함수와 마찬가지로 해당 함수를 임포트해야만 한다.\n<ul>\n<li>이름 충돌을 막기 위함</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">import strings.lastChar as last\n\nval c = &quot;Kotlin&quot;.last()</code>\n        </deckgo-highlight-code>\n<ul>\n<li>as 키워드를 사용하면 다른 이름으로 부를 수 있다.</li>\n<li>확장 함수는 코틀린 문법상 반드시 짧은 이름을 써야 한다.</li>\n</ul>\n<h3 id=\"-332-자바에서-확장-함수-호출\" style=\"position:relative;\"><a href=\"#-332-%EC%9E%90%EB%B0%94%EC%97%90%EC%84%9C-%ED%99%95%EC%9E%A5-%ED%95%A8%EC%88%98-%ED%98%B8%EC%B6%9C\" aria-label=\" 332 자바에서 확장 함수 호출 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>🔖 3.3.2 자바에서 확장 함수 호출</h3>\n<ul>\n<li>확장 함수를 호출해도 다른 어댑터 객체나 실행 시점 부가 비용이 들지 않는다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">char c = StringUtilKt.lastChar(&quot;Java&quot;);</code>\n        </deckgo-highlight-code>\n<ul>\n<li>확장 함수가 StringUtil.kt 파일에 정의했다고 가정하면 자바에서 위와 같이 호출 가능하다.</li>\n</ul>\n<h3 id=\"-333-확장-함수로-유틸리티-함수-정의\" style=\"position:relative;\"><a href=\"#-333-%ED%99%95%EC%9E%A5-%ED%95%A8%EC%88%98%EB%A1%9C-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%95%A8%EC%88%98-%EC%A0%95%EC%9D%98\" aria-label=\" 333 확장 함수로 유틸리티 함수 정의 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>🔖 3.3.3 확장 함수로 유틸리티 함수 정의</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun &lt;T&gt; Collection&lt;T&gt;.joinToString( // Collection&lt;T&gt;에 대한 확장 함수 선언\n    separator: String = &quot;, &quot;,\n    prefix: String = &quot;&quot;,\n    postfix: String = &quot;&quot;\n): String {\n    val result = StringBuilder(prefix)\n\n    for ((index, element) in this.withIndex()) {\n        if (index &gt; 0) result.append(separator)\n        result.append(element)\n    }\n\n    result.append(postfix)\n    return result.toString()\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>joinToString</code>을 클래스의 멤버인 것처럼 호출할 수 있다.</li>\n<li>더 구체적인 타입을 수신 객체 타입으로 지정할 수도 있다.</li>\n</ul>\n<h3 id=\"-334-확장-함수는-오버라이드할-수-없다\" style=\"position:relative;\"><a href=\"#-334-%ED%99%95%EC%9E%A5-%ED%95%A8%EC%88%98%EB%8A%94-%EC%98%A4%EB%B2%84%EB%9D%BC%EC%9D%B4%EB%93%9C%ED%95%A0-%EC%88%98-%EC%97%86%EB%8B%A4\" aria-label=\" 334 확장 함수는 오버라이드할 수 없다 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>🔖 3.3.4 확장 함수는 오버라이드할 수 없다</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun View.showOff() = println(&quot;I&#39;m a view&quot;)\nfun Button.showOff() = println(&quot;I&#39;m a button&quot;)\n\nfun main() {\n    val view: View = Button()\n    view.showOff() // 확장함수는 정적으로 결정된다.\n    // I&#39;m a view\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>확장 함수는 클래스의 일부가 아니다.</li>\n<li>즉, 코틀린은 호출될 확장 함수를 정적으로 결정하기 때문에 오버라이딩이 적용되지 않는다.</li>\n</ul>\n<h3 id=\"-335-확장-프로퍼티\" style=\"position:relative;\"><a href=\"#-335-%ED%99%95%EC%9E%A5-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0\" aria-label=\" 335 확장 프로퍼티 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>🔖 3.3.5 확장 프로퍼티</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val String.lastChar: Char\n    get() = get(length - 1)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>확장 프로퍼티 또한 단지 수신 객체 클래스가 추가됐을 뿐이다.</li>\n<li>뒷받침하는 필드가 없어 기본 게터 구현을 제공할 수 없으므로 꼭 게터는 정의해야 한다.</li>\n<li>확장 프로퍼티를 사용하는 방법은 멤버 프로퍼티를 사용하는 방법과 같다.</li>\n</ul>\n<h2 id=\"-34-컬렉션-처리-가변-길이-인자-중위-함수-호출-라이브러리-지원\" style=\"position:relative;\"><a href=\"#-34-%EC%BB%AC%EB%A0%89%EC%85%98-%EC%B2%98%EB%A6%AC-%EA%B0%80%EB%B3%80-%EA%B8%B8%EC%9D%B4-%EC%9D%B8%EC%9E%90-%EC%A4%91%EC%9C%84-%ED%95%A8%EC%88%98-%ED%98%B8%EC%B6%9C-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%A7%80%EC%9B%90\" aria-label=\" 34 컬렉션 처리 가변 길이 인자 중위 함수 호출 라이브러리 지원 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>📖 3.4 컬렉션 처리: 가변 길이 인자, 중위 함수 호출, 라이브러리 지원</h2>\n<ul>\n<li>vararg 키워드를 사용하면 호출 시 인자 개수가 달라질 수 있는 함수를 정의할 수 있다.</li>\n<li>중위 함수 호출 구문을 사용하면 인자가 하나뿐인 메서드를 간편하게 호출할 수 있다.</li>\n<li>구조 분해 선언을 사용하면 복합적인 값을 분해해서 여러 변수에 나눠 담을 수 있다.</li>\n</ul>\n<h3 id=\"-341-자바-컬렉션-api-확장\" style=\"position:relative;\"><a href=\"#-341-%EC%9E%90%EB%B0%94-%EC%BB%AC%EB%A0%89%EC%85%98-api-%ED%99%95%EC%9E%A5\" aria-label=\" 341 자바 컬렉션 api 확장 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>🔖 3.4.1 자바 컬렉션 API 확장</h3>\n<ul>\n<li>코틀린 표준 라이브러리는 수많은 확장 함수를 포함하고 있다.\n<ul>\n<li>last sum 등</li>\n</ul>\n</li>\n<li>코틀린 파일에서 디폴트로 임포트 된다.</li>\n</ul>\n<h3 id=\"-342-가변-인자-함수-인자의-개수가-달라질-수-있는-함수-정의\" style=\"position:relative;\"><a href=\"#-342-%EA%B0%80%EB%B3%80-%EC%9D%B8%EC%9E%90-%ED%95%A8%EC%88%98-%EC%9D%B8%EC%9E%90%EC%9D%98-%EA%B0%9C%EC%88%98%EA%B0%80-%EB%8B%AC%EB%9D%BC%EC%A7%88-%EC%88%98-%EC%9E%88%EB%8A%94-%ED%95%A8%EC%88%98-%EC%A0%95%EC%9D%98\" aria-label=\" 342 가변 인자 함수 인자의 개수가 달라질 수 있는 함수 정의 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>🔖 3.4.2 가변 인자 함수: 인자의 개수가 달라질 수 있는 함수 정의</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public fun &lt;T&gt; listOf(vararg elements: T): List&lt;T&gt; = if (elements.size &gt; 0) elements.asList() else emptyList()</code>\n        </deckgo-highlight-code>\n<ul>\n<li>원하는 개수만큼 여러 값을 인자로 넘기면 배열에 그 값들을 넣어주는 언어 기능인 varargs를 사용</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main(args: Array&lt;String&gt;) {\n    val list = listOf(&quot;args: &quot;, *args)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린에서는 배열을 명시적으로 풀어 전달해줘야 한다.\n<ul>\n<li>스프레드 연산: 배열 앞에 * 붙이기</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-343-쌍튜플-다루기-중위-호출과-구조-분해-선언\" style=\"position:relative;\"><a href=\"#-343-%EC%8C%8D%ED%8A%9C%ED%94%8C-%EB%8B%A4%EB%A3%A8%EA%B8%B0-%EC%A4%91%EC%9C%84-%ED%98%B8%EC%B6%9C%EA%B3%BC-%EA%B5%AC%EC%A1%B0-%EB%B6%84%ED%95%B4-%EC%84%A0%EC%96%B8\" aria-label=\" 343 쌍튜플 다루기 중위 호출과 구조 분해 선언 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>🔖 3.4.3 쌍(튜플) 다루기: 중위 호출과 구조 분해 선언</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val map = mapOf(1 to &quot;one&quot;, 2 to &quot;two&quot;, 3 to &quot;three&quot;)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>to라는 단어는 코틀린 키워드가 아니다. 중위 호출(infix call) 방식으로 to 라는 일반 메서드를 호출한 것이다.</li>\n<li>중위 호출 시에는 수신 객체 뒤에 메서드 이름을 위치시키고 그 뒤에 유일한 메서드 인자를 넣는다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">infix fun Any.to(other: Any): Pair(this, other)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>함수를 중위 호출에 사용하게 허용하고 싶으면 infix 변경자를 함수 선언 앞에 추가해야 한다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val (number, name) = 1 to &quot;one&quot;</code>\n        </deckgo-highlight-code>\n<ul>\n<li>위와 같은 기능을 구조 분해 선언(destructuring declaration)이라고 부른다.</li>\n</ul>\n<h2 id=\"-35-문자열과-정규식-다루기\" style=\"position:relative;\"><a href=\"#-35-%EB%AC%B8%EC%9E%90%EC%97%B4%EA%B3%BC-%EC%A0%95%EA%B7%9C%EC%8B%9D-%EB%8B%A4%EB%A3%A8%EA%B8%B0\" aria-label=\" 35 문자열과 정규식 다루기 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>📖 3.5 문자열과 정규식 다루기</h2>\n<h3 id=\"-351-문자열-나누기\" style=\"position:relative;\"><a href=\"#-351-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%82%98%EB%88%84%EA%B8%B0\" aria-label=\" 351 문자열 나누기 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>🔖 3.5.1 문자열 나누기</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    println(&quot;12.345-6.A&quot;.split(&quot;\\\\.|-&quot;.toRegex()))\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린에서는 split 함수에 전달하는 값의 타입에 따라 정규식이나 일반 텍스트 중 어느 것으로 분리하는지 쉽게 알 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    println(&quot;12.345-6.A&quot;.split(&#39;.&#39;, &#39;-&#39;))\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>여러 문자를 받을 수 있는 확장 함수도 있다.</li>\n</ul>\n<h3 id=\"-352-정규식과-3중-따옴표로-묶은-문자열\" style=\"position:relative;\"><a href=\"#-352-%EC%A0%95%EA%B7%9C%EC%8B%9D%EA%B3%BC-3%EC%A4%91-%EB%94%B0%EC%98%B4%ED%91%9C%EB%A1%9C-%EB%AC%B6%EC%9D%80-%EB%AC%B8%EC%9E%90%EC%97%B4\" aria-label=\" 352 정규식과 3중 따옴표로 묶은 문자열 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>🔖 3.5.2 정규식과 3중 따옴표로 묶은 문자열</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun parsePath(path: String) {\n    val directory = path.substringBeforeLast(&quot;/&quot;)\n    val fullName = path.substringAfterLast(&quot;/&quot;)\n    val fileName = fullName.substringBeforeLast(&quot;.&quot;)\n    val extension = fullName.substringAfterLast(&quot;.&quot;)\n    \n    println(&quot;Dir: $directory, name: $fileName, ext: $extension&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>정규식을 사용하지 않고도 문자열을 쉽게 파싱할 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun parsePathRegax(path: String) {\n    val regex = &quot;&quot;&quot;(.+)/(.+)\\.(.+)&quot;&quot;&quot;.toRegex()\n    val matchResult = regex.matchEntire(path)\n    if (matchResult != null) {\n        val (directory, filename, extension) = matchResult.destructured\n        println(&quot;Dir: $directory, name: $fileName, ext: $extension&quot;)\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>정규식을 활용하여 파싱할 수 있다.</li>\n<li>3중 따옴표 문자열에서는 \\를 포함한 어떤 문자도 이스케이프할 필요가 없다.</li>\n<li>destructured 프로퍼티: 그룹별로 분해한 매치 결과를 의미</li>\n</ul>\n<h3 id=\"-353-여러-줄-3중-따옴표-문자열\" style=\"position:relative;\"><a href=\"#-353-%EC%97%AC%EB%9F%AC-%EC%A4%84-3%EC%A4%91-%EB%94%B0%EC%98%B4%ED%91%9C-%EB%AC%B8%EC%9E%90%EC%97%B4\" aria-label=\" 353 여러 줄 3중 따옴표 문자열 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>🔖 3.5.3 여러 줄 3중 따옴표 문자열</h3>\n<ul>\n<li>3중 따옴표를 쓰면 줄 바꿈이 들어있는 텍스트를 쉽게 포함시킬 수 있다.</li>\n<li>들여쓰기도 모두 포함된다.</li>\n<li>문자열 템플릿을 사용할 수도 있다.</li>\n<li><code>trimIndent</code> 확장 함수를 호출하면 문자열의 모든 줄에서 가장 짧은 공통 들여쓰기를 찾아 각 줄의 첫 부분에서 제거하고, 공백만으로 이뤄진 첫 번째 줄과 마지막 줄을 제거해준다.</li>\n<li>여러 줄 문자열은 테스트에도 유용하다.</li>\n</ul>\n<h2 id=\"-36-코드-깔끔하게-다듬기-로컬-함수와-확장\" style=\"position:relative;\"><a href=\"#-36-%EC%BD%94%EB%93%9C-%EA%B9%94%EB%81%94%ED%95%98%EA%B2%8C-%EB%8B%A4%EB%93%AC%EA%B8%B0-%EB%A1%9C%EC%BB%AC-%ED%95%A8%EC%88%98%EC%99%80-%ED%99%95%EC%9E%A5\" aria-label=\" 36 코드 깔끔하게 다듬기 로컬 함수와 확장 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>📖 3.6 코드 깔끔하게 다듬기: 로컬 함수와 확장</h2>\n<p>DRY: Don't Repeat Yourself(반복하지 말라)</p>\n<ul>\n<li>코틀린에서는 깔끔하게 코드를 조직할 수 있는 방법이 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class User(val id: Int, val name: String, val address: String)\n\nfun saveUser(user: User) {\n    if (user.name.isEmpty()) {\n        throw IllegalArgumentException(&quot;Can&#39;t save user ${user.id}: empty name&quot;)\n    }\n    if (user.address.isEmpty()) {\n        throw IllegalArgumentException(&quot;Can&#39;t save user ${user.id}: empty address&quot;)\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코드 중복을 보여주는 예제이다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun saveUser(user: User) {\n    fun validate(user: User, value: String, fieldName: String) {\n        if (value.isEmpty()) {\n            throw IllegalArgumentException(&quot;Can&#39;t save user ${user.id}: empty $fieldName&quot;)\n        }\n    }\n    validate(user, user.name, &quot;Name&quot;)\n    validate(user, user.address, &quot;Address&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>조금 나아졌다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class User(val id: Int, val name: String, val address: String)\n\nfun saveUser(user: User) {\n    fun validate(value: String, fieldName: String) {\n        if (value.isEmpty()) {\n            throw IllegalArgumentException(&quot;Can&#39;t save user ${user.id}: &quot; + &quot;empty $fieldName&quot;)\n        }\n    }\n    validate(user.name, &quot;Name&quot;)\n    validate(user.address, &quot;Address&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>바깥 함수의 파라미터에 직접 접근할 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class User(val id: Int, val name: String, val address: String)\n\nfun User.validateBeforeSave() {\n    fun validate(value: String, fieldName: String) {\n        if (value.isEmpty()) {\n            throw IllegalArgumentException(&quot;Can&#39;t save user ${id}: empty $fieldName&quot;)\n        }\n    }\n    validate(name, &quot;Name&quot;)\n    validate(address, &quot;Address&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>확장함수로 추출하기</li>\n<li>확장함수를 로컬 함수로 정의할 수도 있다. 다만, 내포된 함수의 깊이가 깊어지면 읽기가 어려워 일반적으로 한 단계만 함수를 내포시키라고 권장한다.</li>\n</ul>","excerpt":"📖 3.1 코틀린에서 컬렉션 만들기 코틀린은 표준 자바 컬렉션 클래스를 사용한다. 코틀린 컬렉션 인터페이스는 디폴트로 읽기 전용이다. 코틀린 컬렉션은 자바 컬렉션보다 더 많은 기능을 쓸 수 있다! 원소 뒤섞기 등 📖 3.2 함수를 호출하기 쉽게 만들기 덜 번잡하게 만들 수는 없을까? 🔖 3.2.1 이름 붙인 인자 자바의 일부 코딩스타일에서는 method…","fields":{"slug":"/backend/kotlin-in-action/3장-함수_정의와_호출/"},"frontmatter":{"title":"Kotlin in Action - 3장 함수 정의와 호출","thumbnail":{"childImageSharp":{"fluid":{"src":"/static/f7f7ddfa31d1614405dc5af1487b9ec4/9c94d/kotlin-in-action.png"}}},"draft":false,"category":"Back-End","tags":["Kotlin"],"date":"March 16, 2025"}}}},"staticQueryHashes":["2374173507","2996537568","3691437124"]}