{"componentChunkName":"component---src-containers-post-index-tsx","path":"/backend/kotlin-in-action/9장-연산자_오버로딩과_다른_관례/","result":{"pageContext":{"next":{"id":"551d6a82-918e-5d5b-a5da-34a62ef7491d","html":"<h2 id=\"-81-원시-타입과-기본-타입\" style=\"position:relative;\"><a href=\"#-81-%EC%9B%90%EC%8B%9C-%ED%83%80%EC%9E%85%EA%B3%BC-%EA%B8%B0%EB%B3%B8-%ED%83%80%EC%9E%85\" aria-label=\" 81 원시 타입과 기본 타입 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>📖 8.1 원시 타입과 기본 타입</h2>\n<h3 id=\"-811-정수-부동소수점-수-문자-불리언-값을-원시-타입으로-표현\" style=\"position:relative;\"><a href=\"#-811-%EC%A0%95%EC%88%98-%EB%B6%80%EB%8F%99%EC%86%8C%EC%88%98%EC%A0%90-%EC%88%98-%EB%AC%B8%EC%9E%90-%EB%B6%88%EB%A6%AC%EC%96%B8-%EA%B0%92%EC%9D%84-%EC%9B%90%EC%8B%9C-%ED%83%80%EC%9E%85%EC%9C%BC%EB%A1%9C-%ED%91%9C%ED%98%84\" aria-label=\" 811 정수 부동소수점 수 문자 불리언 값을 원시 타입으로 표현 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>🔖 8.1.1 정수, 부동소수점 수, 문자, 불리언 값을 원시 타입으로 표현</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val i: Int = 1\nval list: List&lt;Int&gt; = listOf(1, 2, 3)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린은 원시 타입과 래퍼 타입을 구분하지 않는다.</li>\n<li>매번 객체로 표현하는 것이 아니라 실행 시점에 숫자 타입은 가능한 한 가장 효율적인 방식으로 표현된다.</li>\n</ul>\n<h3 id=\"-812-양수를-표현하기-위해-모든-비트-범위-사용-부호-없는-숫자-타입\" style=\"position:relative;\"><a href=\"#-812-%EC%96%91%EC%88%98%EB%A5%BC-%ED%91%9C%ED%98%84%ED%95%98%EA%B8%B0-%EC%9C%84%ED%95%B4-%EB%AA%A8%EB%93%A0-%EB%B9%84%ED%8A%B8-%EB%B2%94%EC%9C%84-%EC%82%AC%EC%9A%A9-%EB%B6%80%ED%98%B8-%EC%97%86%EB%8A%94-%EC%88%AB%EC%9E%90-%ED%83%80%EC%9E%85\" aria-label=\" 812 양수를 표현하기 위해 모든 비트 범위 사용 부호 없는 숫자 타입 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>🔖 8.1.2 양수를 표현하기 위해 모든 비트 범위 사용: 부호 없는 숫자 타입</h3>\n<table>\n<thead>\n<tr>\n<th>타입</th>\n<th>비트 크기</th>\n<th>표현 범위</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>UByte</code></td>\n<td>8비트</td>\n<td>0 ~ 255</td>\n</tr>\n<tr>\n<td><code>UShort</code></td>\n<td>16비트</td>\n<td>0 ~ 65,535</td>\n</tr>\n<tr>\n<td><code>UInt</code></td>\n<td>32비트</td>\n<td>0 ~ 4,294,967,295</td>\n</tr>\n<tr>\n<td><code>ULong</code></td>\n<td>64비트</td>\n<td>0 ~ 18,446,744,073,709,551,615</td>\n</tr>\n</tbody>\n</table>\n<ul>\n<li>코틀린에는 4가지 부호없는 타입이 있다.</li>\n<li>일반적인 원시 타입을 확장해 부호 없는 타입을 제공한다.</li>\n</ul>\n<h3 id=\"-813-널이-될-수-있는-기본-타입-int-boolean-등\" style=\"position:relative;\"><a href=\"#-813-%EB%84%90%EC%9D%B4-%EB%90%A0-%EC%88%98-%EC%9E%88%EB%8A%94-%EA%B8%B0%EB%B3%B8-%ED%83%80%EC%9E%85-int-boolean-%EB%93%B1\" aria-label=\" 813 널이 될 수 있는 기본 타입 int boolean 등 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>🔖 8.1.3 널이 될 수 있는 기본 타입: Int?, Boolean? 등</h3>\n<ul>\n<li>null 참조를 자바의 참조 타입의 변수에만 대입할 수 있기 때문에 널이 될 수 있는 코틀린 타입은 자바 원시 타입으로 표현할 수 없다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">data class Person(val name: String, val age: Int? = null) {\n    fun isOlderThan(other: Person): Boolean? {\n        if (age == null || other.age == null) {\n            return null\n        }\n        return age &gt; other.age\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>두 값이 널이 아닌지 검사해야 한다.</li>\n<li>컴파일러는 널 검사를 마친 다음에야 두 값을 일반적인 값처럼 다루도록 허용한다.</li>\n</ul>\n<h3 id=\"-814-수-변환\" style=\"position:relative;\"><a href=\"#-814-%EC%88%98-%EB%B3%80%ED%99%98\" aria-label=\" 814 수 변환 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>🔖 8.1.4 수 변환</h3>\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\">val i = 1\nval i: Long = b.toLong() // 자동 변환 X</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\">val x = 1\nval list = listOf(1L, 2L, 3L)\nx in list // false</code>\n        </deckgo-highlight-code>\n<ul>\n<li>암시적 변환을 허용하지 않는다.</li>\n<li>숫자 리터럴을 상요할 때는 변환 함수를 호출할 필요가 없다.\n<ul>\n<li>ex) 1L, 0.2f</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 main() {\n    println(Int.MAX_VALUE + 1)\n    // 음수 최솟값\n    \n    println(Int.MIN_VALUE - 1)\n    // 양수 최댓값\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린 산술 연산자에서도 숫자 연산 시 오버플로나 언더플로가 발생할 수 있다.</li>\n<li>검사하느라 추가비용이 들지 않는다.</li>\n</ul>\n<h3 id=\"-815-any와-any-코틀린-타입-계층의-뿌리\" style=\"position:relative;\"><a href=\"#-815-any%EC%99%80-any-%EC%BD%94%ED%8B%80%EB%A6%B0-%ED%83%80%EC%9E%85-%EA%B3%84%EC%B8%B5%EC%9D%98-%EB%BF%8C%EB%A6%AC\" aria-label=\" 815 any와 any 코틀린 타입 계층의 뿌리 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>🔖 8.1.5 Any와 Any?: 코틀린 타입 계층의 뿌리</h3>\n<ul>\n<li>자바와 달리 Any가 원시 타입을 포함한 모든 타입의 조상 타입이다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val answer: Any = 42</code>\n        </deckgo-highlight-code>\n<ul>\n<li>원시 타입 값을 Any 타입의 변수에 대입하면 자동으로 값을 객체로 감싼다.(박싱)</li>\n<li>Any가 널이 될 수 없는 타입임에 유의</li>\n</ul>\n<h3 id=\"-816-unit-타입-코틀린의-void\" style=\"position:relative;\"><a href=\"#-816-unit-%ED%83%80%EC%9E%85-%EC%BD%94%ED%8B%80%EB%A6%B0%EC%9D%98-void\" aria-label=\" 816 unit 타입 코틀린의 void 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>🔖 8.1.6 Unit 타입: 코틀린의 void</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun f(): Unit {}\nfun f() {}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>Unit을 반환하지만 타입을 지정할 필요는 없다.</li>\n<li>return을 명시할 필요가 없다.\n<ul>\n<li>컴파일러가 암시적으로 <code>return Unit</code>을 넣어준다.</li>\n</ul>\n</li>\n<li>함수형 프로그래밍에서 전통적으로 Unit은 <strong>단 하나의 인스턴스만 갖는 타입</strong>을 의미</li>\n<li>java의 void와 인스턴스의 유무가 가장 큰 차이</li>\n</ul>\n<h3 id=\"-817-nothing-타입-이-함수는-결코-반환되지-않는다\" style=\"position:relative;\"><a href=\"#-817-nothing-%ED%83%80%EC%9E%85-%EC%9D%B4-%ED%95%A8%EC%88%98%EB%8A%94-%EA%B2%B0%EC%BD%94-%EB%B0%98%ED%99%98%EB%90%98%EC%A7%80-%EC%95%8A%EB%8A%94%EB%8B%A4\" aria-label=\" 817 nothing 타입 이 함수는 결코 반환되지 않는다 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>🔖 8.1.7 Nothing 타입: 이 함수는 결코 반환되지 않는다</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun fail(message: String): Nothing {\n    throw IllegalArgumentException(message)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>Nothing 타입은 아무 값도 포함하지 않는다.</li>\n<li>함수의 반환 타입이나 반환 타입으로 쓰일 타입 파라미터로만 쓸 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val address = company.address ?: fail(&quot;No address&quot;)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>Nothing을 반환하는 함수를 엘비스 연산자의 오른쪽에 사용해서 전제조건을 검사할 수 있다.</li>\n</ul>\n<h2 id=\"-82-컬렉션과-배열\" style=\"position:relative;\"><a href=\"#-82-%EC%BB%AC%EB%A0%89%EC%85%98%EA%B3%BC-%EB%B0%B0%EC%97%B4\" aria-label=\" 82 컬렉션과 배열 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>📖 8.2 컬렉션과 배열</h2>\n<h3 id=\"-821-널이-될-수-있는-값의-컬렉션과-널이-될-수-있는-컬렉션\" style=\"position:relative;\"><a href=\"#-821-%EB%84%90%EC%9D%B4-%EB%90%A0-%EC%88%98-%EC%9E%88%EB%8A%94-%EA%B0%92%EC%9D%98-%EC%BB%AC%EB%A0%89%EC%85%98%EA%B3%BC-%EB%84%90%EC%9D%B4-%EB%90%A0-%EC%88%98-%EC%9E%88%EB%8A%94-%EC%BB%AC%EB%A0%89%EC%85%98\" aria-label=\" 821 널이 될 수 있는 값의 컬렉션과 널이 될 수 있는 컬렉션 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>🔖 8.2.1 널이 될 수 있는 값의 컬렉션과 널이 될 수 있는 컬렉션</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun readNumbers(text: String): List&lt;Int?&gt; {\n    val result = mutableListOf&lt;Int?&gt;()\n    for (line in text.lineSequence()) {\n        val numberOrNull = line.toIntOrNull()\n        result.add(numberOrNull)\n    }\n    return result\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>List&#x3C;Int?></code>\n<ul>\n<li>List 자체는 항상 Null이 아니다.</li>\n<li>각 원소는 Null이 될 수 있다.</li>\n</ul>\n</li>\n<li><code>List&#x3C;Int>?</code>\n<ul>\n<li>List는 Null이 될 수 있다.</li>\n<li>각 원소는 Null이 될 수 없다.</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun readNumbers2(text: String): List&lt;Int?&gt; = text.lineSequence().map { it.toIntOrNull() }.toList()</code>\n        </deckgo-highlight-code>\n<ul>\n<li>함수형 프로그래밍으로 간단하게 표현할 수 있다.</li>\n<li>널이 될 수 있는 값으로 이뤄지고, 널이 될 수 있는 리스트를 정의해야 한다면 <code>List&#x3C;Int?>?</code>로 표현할 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">\nfun addValidNumbers(numbers: List&lt;Int?&gt;) {\n    var sumOfValidNumbers = 0\n    var invalidNumbers = 0\n    for (number in numbers) {\n        if (number != null) {\n            sumOfValidNumbers += number\n        } else {\n            invalidNumbers++\n        }\n    }\n    println(&quot;Sum of valid numbers: $sumOfValidNumbers&quot;)\n    println(&quot;Invalid numbers: $invalidNumbers&quot;)\n}\n\nfun main() {\n    val input = &quot;&quot;&quot;\n        1\n        abc\n        42\n    &quot;&quot;&quot;.trimIndent()\n    val numbers = readNumbers(input)\n    addValidNumbers(numbers)\n    // Sum of valid numbers: 43\n    // Invalid numbers: 1\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>filterNotNull</code>을 사용해 간단하게 만들 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun addValidNumbers(numbers: List&lt;Int?&gt;) {\n    val validNumbers = numbers.filterNotNull()\n    println(&quot;Sum of valid numbers: ${validNumbers.sum()}&quot;)\n    println(&quot;Invalid numbers: ${numbers.size - validNumbers.size}&quot;)\n}</code>\n        </deckgo-highlight-code>\n<h3 id=\"-822-읽기-전용과-변경-가능한-컬렉션\" style=\"position:relative;\"><a href=\"#-822-%EC%9D%BD%EA%B8%B0-%EC%A0%84%EC%9A%A9%EA%B3%BC-%EB%B3%80%EA%B2%BD-%EA%B0%80%EB%8A%A5%ED%95%9C-%EC%BB%AC%EB%A0%89%EC%85%98\" aria-label=\" 822 읽기 전용과 변경 가능한 컬렉션 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>🔖 8.2.2 읽기 전용과 변경 가능한 컬렉션</h3>\n<p>코틀린의 컬렉션 인터페이스는 읽기 전용(read-only) 과 변경 가능(mutable) 두 가지 버전이 있다.</p>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun &lt;T&gt; copyElements(source: Collection&lt;T&gt;, target: MutableCollection&lt;T&gt;) {\n    for (item in source) {\n        target.add(item)\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun &lt;T&gt; copyElements(source: Collection&lt;T&gt;, target: MutableCollection&lt;T&gt;) {\n    for (item in source) {\n        target.add(item)\n    }\n}\n\nfun main() {\n    val source: Collection&lt;Int&gt; = arrayListOf(3, 5, 7)\n    val target: Collection&lt;Int&gt; = arrayListOf(1)\n    copyElements(source, target) // 컴파일 에러 발생\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>읽기 전용 컬렉션이 항상 thread safe하지는 않는다.\n<ul>\n<li>내부에서 변경할 수도 있음!</li>\n<li>즉, 불변은 아니다.</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-823-코틀린-컬렉션과-자바-컬렉션은-밀접히-연관됨\" style=\"position:relative;\"><a href=\"#-823-%EC%BD%94%ED%8B%80%EB%A6%B0-%EC%BB%AC%EB%A0%89%EC%85%98%EA%B3%BC-%EC%9E%90%EB%B0%94-%EC%BB%AC%EB%A0%89%EC%85%98%EC%9D%80-%EB%B0%80%EC%A0%91%ED%9E%88-%EC%97%B0%EA%B4%80%EB%90%A8\" aria-label=\" 823 코틀린 컬렉션과 자바 컬렉션은 밀접히 연관됨 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>🔖 8.2.3 코틀린 컬렉션과 자바 컬렉션은 밀접히 연관됨</h3>\n<p>모든 코틀린 컬렉션은 그에 상응하는 자바 컬렉션 인터페이스의 인스턴스이다.</p>\n<ul>\n<li>코틀린의 읽기 전용과 변경 가능 인터페이스의 기본 구조는 <code>java.util</code> 패키지에 있는 자바 컬렉션 인터페이스의 구조와 같다.</li>\n<li>읽기 전용 인터페이스에는 컬렉션을 변경할 수 있는 모든 요소가 빠져있다.</li>\n</ul>\n<table>\n<thead>\n<tr>\n<th>컬렉션 타입</th>\n<th>읽기 전용 타입</th>\n<th>변경 가능 타입</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>List</code></td>\n<td><code>listOf</code>, <code>List</code></td>\n<td><code>mutableListOf</code>, <code>MutableList</code></td>\n</tr>\n<tr>\n<td><code>Set</code></td>\n<td><code>setOf</code></td>\n<td><code>mutableSetOf</code>, <code>MutableSet</code> 등</td>\n</tr>\n<tr>\n<td><code>Map</code></td>\n<td><code>mapOf</code></td>\n<td><code>mutableMapOf</code>, <code>MutableMap</code> 등</td>\n</tr>\n</tbody>\n</table>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public class CollectionUtils {\n    public static List&lt;String&gt; upperCaseAll(List&lt;String&gt; items) {\n        for (int i = 0; i &lt; items.size(); i++) {\n             items.set(i, items.get(i).toUpperCase());\n        }\n        return items;\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun printInUpperCase(list: List&lt;String&gt;) {\n    println(CollectionUtils.upperCaseAll(list))\n    println(list.first())\n}\n\nfun main() {\n    val list = listOf(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;)\n    printInUpperCase(list)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>컬렉션을 변경하는 자바 메서드에게 읽기 전용 <code>Collection</code>을 넘겨도 코틀린 컴파일러가 이를 막을 수 없다.</li>\n<li>컬렉션을 자바 코드에게 넘길 때는 특별히 주의를 기울여야 한다.</li>\n</ul>\n<h3 id=\"-824-자바에서-선언한-컬렉션은-코틀린에서-플랫폼-타입으로-보임\" style=\"position:relative;\"><a href=\"#-824-%EC%9E%90%EB%B0%94%EC%97%90%EC%84%9C-%EC%84%A0%EC%96%B8%ED%95%9C-%EC%BB%AC%EB%A0%89%EC%85%98%EC%9D%80-%EC%BD%94%ED%8B%80%EB%A6%B0%EC%97%90%EC%84%9C-%ED%94%8C%EB%9E%AB%ED%8F%BC-%ED%83%80%EC%9E%85%EC%9C%BC%EB%A1%9C-%EB%B3%B4%EC%9E%84\" aria-label=\" 824 자바에서 선언한 컬렉션은 코틀린에서 플랫폼 타입으로 보임 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>🔖 8.2.4 자바에서 선언한 컬렉션은 코틀린에서 플랫폼 타입으로 보임</h3>\n<ul>\n<li>플랫폼 타입의 경우 코틀린 쪽에는 널 관련 정보가 없다.</li>\n<li>자바 쪽에서 선언한 컬렉션 타입의 변수를 코틀린에서는 플랫폼 타입으로 본다.</li>\n<li>컬렉션 타입이 시그니처에 들어간 자바 메서드 구현을 오버라이드하려는 경우 읽기 전용 컬렉션과 변경 가능 컬렉션의 차이가 문제가 된다.\n<ul>\n<li>컬렉션이 null이 될 수 있는가?</li>\n<li>컬렉션의 원소가 null이 될 수 있는가?</li>\n<li>여러번이 작성할 메서드가 컬렉션을 변경할 수 있는가?</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public interface FileContentProcessor {\n    void processContents(File path, byte[] binaryContents, List&lt;String&gt; textContents);\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 FileIndexer : FileContentProcessor {\n    override fun processContents(path: File, binaryContents: ByteArray?, textContents: MutableList&lt;String&gt;?) {\n        TODO(&quot;Not yet implemented&quot;)\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface DataParser&lt;T&gt; {\n    void parseData(\n            String input,\n            List&lt;T&gt; output,\n            List&lt;String&gt; errors\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\">class PersonParser : DataParser&lt;Person&gt; {\n    override fun parseData(input: String, output: MutableList&lt;Person&gt;, errors: MutableList&lt;String?&gt;) {\n        TODO(&quot;Not yet implemented&quot;)\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>java 인터페이스나 클래스가 어떤 맥락에서 사용되는지 정확히 알아야 한다.</li>\n</ul>\n<h3 id=\"-825-성능과-상호운용을-위해-객체의-배열이나-원시-타입의-배열을-만들기\" style=\"position:relative;\"><a href=\"#-825-%EC%84%B1%EB%8A%A5%EA%B3%BC-%EC%83%81%ED%98%B8%EC%9A%B4%EC%9A%A9%EC%9D%84-%EC%9C%84%ED%95%B4-%EA%B0%9D%EC%B2%B4%EC%9D%98-%EB%B0%B0%EC%97%B4%EC%9D%B4%EB%82%98-%EC%9B%90%EC%8B%9C-%ED%83%80%EC%9E%85%EC%9D%98-%EB%B0%B0%EC%97%B4%EC%9D%84-%EB%A7%8C%EB%93%A4%EA%B8%B0\" aria-label=\" 825 성능과 상호운용을 위해 객체의 배열이나 원시 타입의 배열을 만들기 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>🔖 8.2.5 성능과 상호운용을 위해 객체의 배열이나 원시 타입의 배열을 만들기</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main(args: Array&lt;String&gt;) {\n    for (i in args.indices) {\n        println(&quot;Argument $i is: ${args[i]}&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 letters = Array&lt;String&gt;(26) { i -&gt; (&#39;a&#39; + i).toString() }\n    println(letters.joinToString(&quot;&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 main() {\n    val letters = Array(26) { i -&gt; (&#39;a&#39; + i).toString() }\n    println(letters.joinToString(&quot;&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 main() {\n    val strings = listOf(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;)\n    println(&quot;%s/%s/%s&quot;.format(*strings.toTypedArray())) // 스프레드 연산자 사용\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\">val fiveZeros = IntArray(5)\nval fiveZerosToo = intArrayOf(0, 0, 0, 0, 0)\n\nfun main() {\n    val squares = IntArray(5) { i -&gt; (i + 1) * (i + 1) }\n    println(squares.joinToString())\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>배열을 만드는 방법은 다양하다.</li>\n</ul>","excerpt":"📖 8.1 원시 타입과 기본 타입 🔖 8.1.1 정수, 부동소수점 수, 문자, 불리언 값을 원시 타입으로 표현 코틀린은 원시 타입과 래퍼 타입을 구분하지 않는다. 매번 객체로 표현하는 것이 아니라 실행 시점에 숫자 타입은 가능한 한 가장 효율적인 방식으로 표현된다. 🔖 8.1.2 양수를 표현하기 위해 모든 비트 범위 사용: 부호 없는 숫자 타입 타입 비트 크기 표현 범위 UByte 8비트 0 ~ 255 UShort 16비트 0 ~ 65,535 UInt 32비트 0 ~ 4,294,967,29…","fields":{"slug":"/backend/kotlin-in-action/8장-기본_타입_컬렉션_배열/"},"frontmatter":{"title":"Kotlin in Action - 8장 기본 타입, 컬렉션, 배열","thumbnail":{"childImageSharp":{"fluid":{"src":"/static/f7f7ddfa31d1614405dc5af1487b9ec4/9c94d/kotlin-in-action.png"}}},"draft":false,"category":"Back-End","tags":["Kotlin"],"date":"April 20, 2025"}},"previous":{"id":"19b26918-c9bd-5dc5-9a91-76021099d3ff","html":"<h2 id=\"-101-다른-함수를-인자로-받거나-반환하는-함수-정의-고차-함수\" style=\"position:relative;\"><a href=\"#-101-%EB%8B%A4%EB%A5%B8-%ED%95%A8%EC%88%98%EB%A5%BC-%EC%9D%B8%EC%9E%90%EB%A1%9C-%EB%B0%9B%EA%B1%B0%EB%82%98-%EB%B0%98%ED%99%98%ED%95%98%EB%8A%94-%ED%95%A8%EC%88%98-%EC%A0%95%EC%9D%98-%EA%B3%A0%EC%B0%A8-%ED%95%A8%EC%88%98\" aria-label=\" 101 다른 함수를 인자로 받거나 반환하는 함수 정의 고차 함수 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>📖 10.1 다른 함수를 인자로 받거나 반환하는 함수 정의: 고차 함수</h2>\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\">list.filter { it &gt; 0}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>표준 라이브러리 함수인 filter는 술어 함수를 인자로 받으므로 고차 함수</li>\n</ul>\n<h3 id=\"-1011-함수-타입은-람다의-파라미터-타입과-반환-타입을-지정한다\" style=\"position:relative;\"><a href=\"#-1011-%ED%95%A8%EC%88%98-%ED%83%80%EC%9E%85%EC%9D%80-%EB%9E%8C%EB%8B%A4%EC%9D%98-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0-%ED%83%80%EC%9E%85%EA%B3%BC-%EB%B0%98%ED%99%98-%ED%83%80%EC%9E%85%EC%9D%84-%EC%A7%80%EC%A0%95%ED%95%9C%EB%8B%A4\" aria-label=\" 1011 함수 타입은 람다의 파라미터 타입과 반환 타입을 지정한다 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>🔖 10.1.1 함수 타입은 람다의 파라미터 타입과 반환 타입을 지정한다</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val sum = { x: Int, y: Int -&gt; x + y }\nval action = { println(42) }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>컴파일러는 sum과 action이 함수 타입임을 추론</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val sum: (Int, Int) -&gt; Int = { x, y -&gt; x + y } // Int 파라미터를 2개 받아서 Int 값을 반환하는 함수\nval action: () -&gt; Unit = { println(42) } // 아무 인자도 받지 않고 아무 값도 반환하지 않는 함수</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\">var canReturnNu11: (Int, Int) -&gt; Int? = { x, y -&gt; null }</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\">var funOrNull: ((Int, Int) -&gt; Int)? = null</code>\n        </deckgo-highlight-code>\n<ul>\n<li>함수 전체가 널이 될 수 있는 타입임을 선언하기 위해 함수 타입을 괄호로 감싸고 그 뒤에 물음표를 붙여야만 한다.</li>\n</ul>\n<h3 id=\"-1012-인자로-전달-받은-함수-호출\" style=\"position:relative;\"><a href=\"#-1012-%EC%9D%B8%EC%9E%90%EB%A1%9C-%EC%A0%84%EB%8B%AC-%EB%B0%9B%EC%9D%80-%ED%95%A8%EC%88%98-%ED%98%B8%EC%B6%9C\" aria-label=\" 1012 인자로 전달 받은 함수 호출 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>🔖 10.1.2 인자로 전달 받은 함수 호출</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun twoAndThree(operation: (Int, Int) -&gt; Int) {\n    val result = operation(2, 3)\n    println(&quot;The result is $result&quot;)\n}\n\nfun main() {\n    twoAndThree { a, b -&gt; a + b }\n    // The result is 5\n    twoAndThree { a, b -&gt; a * b }\n    // The result is 6\n}</code>\n        </deckgo-highlight-code>\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\">fun String.filter(predicate: (Char) -&gt; Boolean): String {\n    return buildString {\n        for (char in this@filter) {\n            if (predicate(char)) append(char)\n        }\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>filter 함수는 술어를 파라미터로 받는다.</li>\n<li>확장 함수와 buildString 함수 모두 수신 객체를 정의하기 때문에 this 앞에 레이블읇 붙여 buildString 람다의 수신 객체가 아니라 filter의 바깥쪽 수신 객체에 접근해야 한다.</li>\n</ul>\n<h3 id=\"-1013-자바에서-코틀린-함수-타입-사용\" style=\"position:relative;\"><a href=\"#-1013-%EC%9E%90%EB%B0%94%EC%97%90%EC%84%9C-%EC%BD%94%ED%8B%80%EB%A6%B0-%ED%95%A8%EC%88%98-%ED%83%80%EC%9E%85-%EC%82%AC%EC%9A%A9\" aria-label=\" 1013 자바에서 코틀린 함수 타입 사용 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>🔖 10.1.3 자바에서 코틀린 함수 타입 사용</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun processTheAnswer (f: (Int) -&gt; Int) {\n    printin(f(42))\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">processTheAnswer(number -&gt; number + 1);</code>\n        </deckgo-highlight-code>\n<ul>\n<li>자동 SAM 변환을 통해 코틀린 람다를 함수형 인터페이스를 요구하는 자바 메서드에게 넘길 수 있다. 즉, 자바에서 정의된 고차 함수를 아무 문제 없이 사용할 수 있다는 의미다.</li>\n<li>자바에서 람다를 인자로 받는 코틀린 확장함수를 사용할 때는 첫 번째 인자로 수신 객체를 명시적으로 전달해야 한다.</li>\n</ul>\n<h3 id=\"-1014-함수-타입의-파라미터에-대해-기본값을-지정할-수-있고-널이-될-수도-있다\" style=\"position:relative;\"><a href=\"#-1014-%ED%95%A8%EC%88%98-%ED%83%80%EC%9E%85%EC%9D%98-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0%EC%97%90-%EB%8C%80%ED%95%B4-%EA%B8%B0%EB%B3%B8%EA%B0%92%EC%9D%84-%EC%A7%80%EC%A0%95%ED%95%A0-%EC%88%98-%EC%9E%88%EA%B3%A0-%EB%84%90%EC%9D%B4-%EB%90%A0-%EC%88%98%EB%8F%84-%EC%9E%88%EB%8B%A4\" aria-label=\" 1014 함수 타입의 파라미터에 대해 기본값을 지정할 수 있고 널이 될 수도 있다 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>🔖 10.1.4 함수 타입의 파라미터에 대해 기본값을 지정할 수 있고, 널이 될 수도 있다.</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(separator: String = &quot;, &quot;, prefix: String = &quot;&quot;, postfix: String = &quot;&quot;): 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    result.append(postfix)\n    return result.toString()\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 &lt;T&gt; Collection&lt;T&gt;.joinToString(separator: String = &quot;, &quot;, prefix: String = &quot;&quot;, postfix: String = &quot;&quot;, transform: (T) -&gt; String = { it.toString() }): 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(transform(element))\n    }\n    result.append(postfix)\n    return result.toString()\n}</code>\n        </deckgo-highlight-code>\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\">fun &lt;T&gt; Collection&lt;T&gt;.joinToString(separator: String = &quot;, &quot;, prefix: String = &quot;&quot;, postfix: String = &quot;&quot;, transform: ((T) -&gt; String)? = null): String {\n    val result = StringBuilder(prefix)\n\n    for ((index, element) in this.withIndex()) {\n        if (index &gt; 0) result.append(separator)\n        val str = transform?.invoke(element) ?: element.toString()\n        result.append(str)\n    }\n    result.append(postfix)\n    return result.toString()\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>transform은 넘이 될 수 있는 함수 타입이지만 그 반환 타입은 널이 될 수 없는 타입이다.</li>\n<li>transform은 자신이 null이 아니면 String 타입의 널이 아닌 값을 반환한다는 사실을 보장한다.</li>\n</ul>\n<h3 id=\"-1015-함수를-함수에서-반환\" style=\"position:relative;\"><a href=\"#-1015-%ED%95%A8%EC%88%98%EB%A5%BC-%ED%95%A8%EC%88%98%EC%97%90%EC%84%9C-%EB%B0%98%ED%99%98\" aria-label=\" 1015 함수를 함수에서 반환 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>🔖 10.1.5 함수를 함수에서 반환</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun getShippingCostCalculator(delivery: Delivery): (Order) -&gt; Double {\n    if (delivery == Delivery.EXPEDITED) {\n        return { order -&gt; 6 + 2.1 * order.itemCount }\n    }\n    return { order -&gt; 1.2 * order.itemCount }\n}\n\nfun main() {\n    val calculator = getShippingCostCalculator(Delivery.EXPEDITED)\n    println(&quot;Shipping costs ${calculator(Order(3))}&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 ContactListFilters {\n    var prefix: String = &quot;&quot;\n    var onlyWithPhoneNumber: Boolean = false\n\n    fun getPredicate(): (Person) -&gt; Boolean {\n        val startWithPrefix = { p: Person -&gt; p.firstName.startsWith(prefix) || p.lastName.startsWith(prefix)}\n        if (!onlyWithPhoneNumber) {\n            return startWithPrefix\n        }\n        return { startWithPrefix(it) &amp;&amp; it.phoneNumber != null }\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>getPredicate method는 filter 함수에 인자로 넘길 수 있는 함수를 반환한다.</li>\n<li>고차 함수는 코드 구조를 개선하고 중복을 없앨 때 쓸 수 있는 아주 강력한 도구다.</li>\n</ul>\n<h3 id=\"-1016-람다를-활용해-중복을-줄여-코드-재사용성-높이기\" style=\"position:relative;\"><a href=\"#-1016-%EB%9E%8C%EB%8B%A4%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%B4-%EC%A4%91%EB%B3%B5%EC%9D%84-%EC%A4%84%EC%97%AC-%EC%BD%94%EB%93%9C-%EC%9E%AC%EC%82%AC%EC%9A%A9%EC%84%B1-%EB%86%92%EC%9D%B4%EA%B8%B0\" aria-label=\" 1016 람다를 활용해 중복을 줄여 코드 재사용성 높이기 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>🔖 10.1.6 람다를 활용해 중복을 줄여 코드 재사용성 높이기</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">data class SiteVisit(\n    val path: String,\n    val duration: Double,\n    val os: OS\n)\n\nenum class OS { WINDOWS, LINUX, MAC, IOS, ANDROID }\n\nval log = listOf(\n    SiteVisit(&quot;/&quot;, 34.0, OS.WINDOWS),\n    SiteVisit(&quot;/&quot;, 22.0, OS.MAC),\n    SiteVisit(&quot;/login&quot;, 12.0, OS.WINDOWS),\n    SiteVisit(&quot;/signup&quot;, 8.0, OS.IOS),\n    SiteVisit(&quot;/&quot;, 16.3, OS.ANDROID),\n)\n\nval averageWindowsDuration = log\n    .filter { it.os == OS.WINDOWS }\n    .map(SiteVisit::duration)\n    .average()</code>\n        </deckgo-highlight-code>\n<ul>\n<li>윈도우 사용자의 평균 방문 시간 출력은 average 함수로 쉽게 표현할 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun List&lt;SiteVisit&gt;.averageDurationFor(os: OS) = filter { it.os == os }.map(SiteVisit::duration).average()</code>\n        </deckgo-highlight-code>\n<ul>\n<li>중복을 피하기 위해 OS를 파라미터로 뽑아낼 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun List&lt;SiteVisit&gt;.averageDurationFor(predicate: (SiteVisit) -&gt; Boolean) = filter(SiteVisit).map(SiteVisit::duration).average()</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코드 중복을 줄일 때 함수 타입이 상당히 도움이 된다.</li>\n</ul>\n<h2 id=\"-102-인라인-함수를-사용해-람다의-부가-비용-없애기\" style=\"position:relative;\"><a href=\"#-102-%EC%9D%B8%EB%9D%BC%EC%9D%B8-%ED%95%A8%EC%88%98%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%B4-%EB%9E%8C%EB%8B%A4%EC%9D%98-%EB%B6%80%EA%B0%80-%EB%B9%84%EC%9A%A9-%EC%97%86%EC%95%A0%EA%B8%B0\" aria-label=\" 102 인라인 함수를 사용해 람다의 부가 비용 없애기 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>📖 10.2 인라인 함수를 사용해 람다의 부가 비용 없애기</h2>\n<ul>\n<li>inline 변경자를 어떤 함수에 붙이면 컴파일러는 그 함수가 쓰이는 위치에 함수 호출을 생성하는 대신에 함수를 구현하는 코드로 바꿔치기 해준다.</li>\n</ul>\n<h3 id=\"-1021-인라이닝이-작동하는-방식\" style=\"position:relative;\"><a href=\"#-1021-%EC%9D%B8%EB%9D%BC%EC%9D%B4%EB%8B%9D%EC%9D%B4-%EC%9E%91%EB%8F%99%ED%95%98%EB%8A%94-%EB%B0%A9%EC%8B%9D\" aria-label=\" 1021 인라이닝이 작동하는 방식 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>🔖 10.2.1 인라이닝이 작동하는 방식</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">inline fun &lt;T&gt; synchronized(lock: Lock, action: () -&gt; T): T {\n    lock.lock()\n    try {\n        return action()\n    }\n    finally {\n        lock.unlock()\n    }\n}\n\nfun main() {\n    val l = ReentrantLock()\n    synchronized(1) {\n        // ...\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>어떤 함수를 inline으로 선언하면 그 함수의 본문이 인라인된다.\n<ul>\n<li>함수를 호출하는 코드를 함수를 호출하는 바이트코드 대신에 함수 본문을 번역한 바이트코드로 컴파일한다는 뜻</li>\n</ul>\n</li>\n<li>synchronized 함수를 inline으로 선언했으므로 synchronized를 호출하는 코드는 모두 자바의 synchronized 문과 같아진다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class LockOwner(val lock: Lock) {\n    fun runUnderLock(body: () -&gt; Unit) {\n        synchronized(lock, body)\n    } \n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>인라인 함수를 호출하면서 람다를 넘기는 대신에 함수 타입의 변수를 넘길 수도 있다.</li>\n<li>함수에 더해 프로퍼티 접근자에도 inline을 붙일 수 있다.</li>\n</ul>\n<h3 id=\"-1022-인라인-함수의-제약\" style=\"position:relative;\"><a href=\"#-1022-%EC%9D%B8%EB%9D%BC%EC%9D%B8-%ED%95%A8%EC%88%98%EC%9D%98-%EC%A0%9C%EC%95%BD\" aria-label=\" 1022 인라인 함수의 제약 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>🔖 10.2.2 인라인 함수의 제약</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class FunctionStorage {\n    var myStoredFunction: ((Int) -&gt; Unit)? = null\n    inline fun storeFunction(f: (Int) -&gt; Unit) { \n        myStoredFunction = f // error\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 &lt;T, R&gt; Sequence&lt;T&gt;.map(transform: (T) -&gt; R): Sequence&lt;R&gt; {\n    return TransformingSequence(this, transform)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>Sequence.map 의 정의다.</li>\n<li>transform 파라미터로 전달받은 함수 값을 호출하지 않는 대신, TransformingSequence라는 클래스의 생성자에게 그 함수 값을 넘긴다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">inline fun foo(inlined: () -&gt; Unit, noinline notInlined: () -&gt; Unit) {\n    //..\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>인라이닝하면 안 되는 람다를 파라미터로 받는다면 noinline 변경자를 파라미터 이름 앞에 붙여 인라이닝을 금지할 수 있다.</li>\n</ul>\n<h3 id=\"-1023-컬렉션-연산-인라이닝\" style=\"position:relative;\"><a href=\"#-1023-%EC%BB%AC%EB%A0%89%EC%85%98-%EC%97%B0%EC%82%B0-%EC%9D%B8%EB%9D%BC%EC%9D%B4%EB%8B%9D\" aria-label=\" 1023 컬렉션 연산 인라이닝 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>🔖 10.2.3 컬렉션 연산 인라이닝</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">data class Person(val name: String, val age: Int)\n\nval people = listOf(Person(&quot;Alice&quot;, 29), Person(&quot;Bob&quot;, 31))\n\nfun main() {\n    println(people.filter { it.age &lt; 30 })\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 result = mutableListOf&lt;Person&gt;()\n    for (person in people) {\n        if (person.age &lt; 30) {\n            result.add(person)\n        }\n    }\n    println(result)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린에서 filter는 인라인 함수다.</li>\n<li>즉, filter를 써서 생긴 바이트코드와 위 예제는 거의 같다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    println(\n        people.filter { it.age &lt; 30 }\n            .map(Person::name)\n    )\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>map도 인라인 함수다.</li>\n<li>시퀀스에 사용된 람다는 인라이닝되지 않는다. 따라서 지연 계산을 통해 성능을 향상시키려는 이유로 모든 컬렉션 연산에 asSequence를 붙이려고 해서는 안 된다.</li>\n<li>시퀀스를 통해 성능을 향상시킬 수 있는 경우는 컬렉션 크기가 큰 경우뿐이다.</li>\n</ul>\n<h3 id=\"-1024-언제-함수를-인라인으로-선언할지-결정\" style=\"position:relative;\"><a href=\"#-1024-%EC%96%B8%EC%A0%9C-%ED%95%A8%EC%88%98%EB%A5%BC-%EC%9D%B8%EB%9D%BC%EC%9D%B8%EC%9C%BC%EB%A1%9C-%EC%84%A0%EC%96%B8%ED%95%A0%EC%A7%80-%EA%B2%B0%EC%A0%95\" aria-label=\" 1024 언제 함수를 인라인으로 선언할지 결정 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>🔖 10.2.4 언제 함수를 인라인으로 선언할지 결정</h3>\n<ul>\n<li>inline 키워드를 사용해도 람다를 인자로 받는 함수만 성능이 좋아질 가능성이 높다.</li>\n<li>일반 함수 호출의 경우 JVM은 이미 강력하게 인라이닝을 지원한다.\n<ul>\n<li>바이트코드를 실제 기계어 코드로 번역하는 과정(JIT)에서 일어난다.</li>\n</ul>\n</li>\n<li>바이트코드에서는 각 함수 구현이 정확히 한 번만 있으면 되고 그 함수를 호출하는 모든 부분에 따로 코드를 중복할 필요가 없다. 반면, 코틀린 인라인 함수는 코드 중복이 생긴다.</li>\n<li>람다를 인자로 받는 함수를 인라이닝하면 이익이 더 많다.\n<ul>\n<li>함수 호출 비용 감소</li>\n<li>람다를 표현하는 클래스와 람다 인스턴스에 해당하는 객체를 만들 필요도 없어진다.</li>\n<li>JVM은 함수 호출과 람다를 인라이닝해줄 정도로 똑똑하지 못하다.</li>\n<li>추가 기능을 사용할 수 있다.</li>\n</ul>\n</li>\n<li>inline 변경자를 함수에 붙일 때는 코드 크기에 주의를 기울여야 한다.</li>\n</ul>\n<h3 id=\"-1025-withlock-use-uselines로-자원-관리를-위해-인라인된-람다-사용\" style=\"position:relative;\"><a href=\"#-1025-withlock-use-uselines%EB%A1%9C-%EC%9E%90%EC%9B%90-%EA%B4%80%EB%A6%AC%EB%A5%BC-%EC%9C%84%ED%95%B4-%EC%9D%B8%EB%9D%BC%EC%9D%B8%EB%90%9C-%EB%9E%8C%EB%8B%A4-%EC%82%AC%EC%9A%A9\" aria-label=\" 1025 withlock use uselines로 자원 관리를 위해 인라인된 람다 사용 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>🔖 10.2.5 withLock, use, useLines로 자원 관리를 위해 인라인된 람다 사용</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val l: Lock = ReentrantLock()\nl.withLock {\n    //..\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>withLock은 락을 획득한 후 작업하는 숙어를 별도의 함수로 분리</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun readFirstLineFromFile(fileName: String): String {\n    BufferedReader(FileReader(fileName)).use { br -&gt;\n        return br.readLine()\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>use 함수는 닫을 수 있는 자원에 대해 호출하는 확장 함수다.\n<ul>\n<li>람다를 호출하고 사용 후 자원이 확실히 닫히게 한다.</li>\n</ul>\n</li>\n<li>use 함수는 인라인 함수이며, 성능에는 영향이 없다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun readFirstLineFromFile(fileName: String): String {\n    Path(fileName).useLines { \n        return it.first()\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>use는 Closeable과 함께 쓰이지만 useLines는 File과 Path 객체에 정의돼 있고, 람다가 문자열 시퀀스에 접근하게 해준다.</li>\n</ul>\n<h2 id=\"-103-람다에서-반환-고차-함수에서-흐름-제어\" style=\"position:relative;\"><a href=\"#-103-%EB%9E%8C%EB%8B%A4%EC%97%90%EC%84%9C-%EB%B0%98%ED%99%98-%EA%B3%A0%EC%B0%A8-%ED%95%A8%EC%88%98%EC%97%90%EC%84%9C-%ED%9D%90%EB%A6%84-%EC%A0%9C%EC%96%B4\" aria-label=\" 103 람다에서 반환 고차 함수에서 흐름 제어 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>📖 10.3 람다에서 반환: 고차 함수에서 흐름 제어</h2>\n<h3 id=\"-1031-람다-안의-return-문-람다를-둘러싼-함수에서-반환\" style=\"position:relative;\"><a href=\"#-1031-%EB%9E%8C%EB%8B%A4-%EC%95%88%EC%9D%98-return-%EB%AC%B8-%EB%9E%8C%EB%8B%A4%EB%A5%BC-%EB%91%98%EB%9F%AC%EC%8B%BC-%ED%95%A8%EC%88%98%EC%97%90%EC%84%9C-%EB%B0%98%ED%99%98\" aria-label=\" 1031 람다 안의 return 문 람다를 둘러싼 함수에서 반환 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>🔖 10.3.1 람다 안의 return 문: 람다를 둘러싼 함수에서 반환</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">data class Person(val name: String, val age: Int)\n\nval people = listOf(Person(&quot;Alice&quot;, 29), Person(&quot;Bob&quot;, 31))\n\nfun lookForAlice(people: List&lt;Person&gt;) {\n    for (person in people) {\n        if (person.name == &quot;Alice&quot;) {\n            println(&quot;Found!&quot;)\n            return\n        }\n    }\n    println(&quot;Alice is not found&quot;)\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun lookForAlice(people: List&lt;Person&gt;) {\n    people.forEach {\n        if (it.name == &quot;Alice&quot;) {\n            println(&quot;Found!&quot;)\n            return\n        }\n    }\n    println(&quot;Alice is not found&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>위 두 예제는 같은 의미다.</li>\n<li>람다 안에서 return을 사용하면 람다에서만 반환되는 것이 아니라 그 람다를 호출하는 함수가 실행을 끝내고 반환된다.</li>\n<li>비로컬 return: 자신을 둘러쌓고 있는 블록보다 더 바깥에 있는 다른 블록을 반환하게 만드는 return 문</li>\n<li>return이 바깥쪽 함수를 반환시킬 수 있는 때는 람다를 인자로 받는 함수가 인라인 함수인 경우다.\n<ul>\n<li>인라이닝되지 않는 함수에 전달되는 람다 안에서 return을 사용할 수는 없다.</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-1032-람다로부터-반환-레이블을-사용한-return\" style=\"position:relative;\"><a href=\"#-1032-%EB%9E%8C%EB%8B%A4%EB%A1%9C%EB%B6%80%ED%84%B0-%EB%B0%98%ED%99%98-%EB%A0%88%EC%9D%B4%EB%B8%94%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%9C-return\" aria-label=\" 1032 람다로부터 반환 레이블을 사용한 return 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>🔖 10.3.2 람다로부터 반환: 레이블을 사용한 return</h3>\n<ul>\n<li>로컬 return: 람다의 실행을 끝내고 람다를 호출했던 코드의 실행을 계속 이어간다.</li>\n<li>로컬 return과 비로컬 return을 구분하기 위해 레이블을 사용한다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun lookForAlice(people: List&lt;Person&gt;) {\n    people.forEach label@{\n        if (it.name != &quot;Alice&quot;) return@label\n        println(&quot;Found Alice&quot;)\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>return으로 실행을 끝내고 싶은 람다식 앞에 레이블을 붙인다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun lookForAlice(people: List&lt;Person&gt;) {\n    people.forEach {\n        if (it.name != &quot;Alice&quot;) return@forEach\n        println(&quot;Found Alice!&quot;)\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>람다식의 레이블을 명시하면 함수 이름을 레이블로 사용할 수 없다는 점에 유의</li>\n</ul>\n<h3 id=\"-1033-익명-함수-기본적으로-로컬-return\" style=\"position:relative;\"><a href=\"#-1033-%EC%9D%B5%EB%AA%85-%ED%95%A8%EC%88%98-%EA%B8%B0%EB%B3%B8%EC%A0%81%EC%9C%BC%EB%A1%9C-%EB%A1%9C%EC%BB%AC-return\" aria-label=\" 1033 익명 함수 기본적으로 로컬 return 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>🔖 10.3.3 익명 함수: 기본적으로 로컬 return</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun lookForAlice(people: List&lt;Person&gt;) {\n    people.forEach (fun (person) {\n        if (person.name == &quot;Alice&quot;) return\n        println(&quot;${person.name} is not Alice&quot;)\n    })\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>return은 가장 가까운 함수를 가리킨다.</li>\n<li>익명 함수 안에서 레이블이 붙지 않은 return 식은 익명 함수 자체를 반환시킬 뿐 익명 함수를 둘러싼 다른 함수를 반환시키지 않는다.</li>\n<li>익명 함수는 일반 함수와 비슷해 보이지만 실제로는 람다식에 대한 문법적 편의일 뿐이다.</li>\n</ul>","excerpt":"📖 10.1 다른 함수를 인자로 받거나 반환하는 함수 정의: 고차 함수 고차 할수는 다른 할수를 인자로 받거나 함수를 반환하는 합수 코물린에서는 다나 할수 참조를 사용해 함수를 값으로 표현할 수 있다. 표준 라이브러리 함수인 filter는 술어 함수를 인자로 받으므로 고차 함수 🔖 10.1.1 함수 타입은 람다의 파라미터 타입과 반환 타입을 지정한다 컴파일러는 sum과 action…","fields":{"slug":"/backend/kotlin-in-action/10장-고차함수-람다를_파라미터와_반환값으로_사용/"},"frontmatter":{"title":"Kotlin in Action - 10장 고차 함수: 람다를 파라미터와 반환값으로 사용","thumbnail":{"childImageSharp":{"fluid":{"src":"/static/f7f7ddfa31d1614405dc5af1487b9ec4/9c94d/kotlin-in-action.png"}}},"draft":false,"category":"Back-End","tags":["Kotlin"],"date":"May 11, 2025"}},"node":{"id":"dd1d7589-298b-5305-9cd3-3de0eb0cc3f7","html":"<p>코틀린은 어떤 언어 기능과 미리 정해진 이름의 함수를 연결해주는 기법인 관례에 의존한다.</p>\n<h2 id=\"-91-산술-연산자를-오버로드해서-임의의-클래스에-대한-연산을-더-편리하게-만들기\" style=\"position:relative;\"><a href=\"#-91-%EC%82%B0%EC%88%A0-%EC%97%B0%EC%82%B0%EC%9E%90%EB%A5%BC-%EC%98%A4%EB%B2%84%EB%A1%9C%EB%93%9C%ED%95%B4%EC%84%9C-%EC%9E%84%EC%9D%98%EC%9D%98-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%97%90-%EB%8C%80%ED%95%9C-%EC%97%B0%EC%82%B0%EC%9D%84-%EB%8D%94-%ED%8E%B8%EB%A6%AC%ED%95%98%EA%B2%8C-%EB%A7%8C%EB%93%A4%EA%B8%B0\" aria-label=\" 91 산술 연산자를 오버로드해서 임의의 클래스에 대한 연산을 더 편리하게 만들기 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>📖 9.1 산술 연산자를 오버로드해서 임의의 클래스에 대한 연산을 더 편리하게 만들기</h2>\n<h3 id=\"-911-plus-times-divide-등-이항-산술-연산-오버로딩\" style=\"position:relative;\"><a href=\"#-911-plus-times-divide-%EB%93%B1-%EC%9D%B4%ED%95%AD-%EC%82%B0%EC%88%A0-%EC%97%B0%EC%82%B0-%EC%98%A4%EB%B2%84%EB%A1%9C%EB%94%A9\" aria-label=\" 911 plus times divide 등 이항 산술 연산 오버로딩 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>🔖 9.1.1 plus, times, divide 등: 이항 산술 연산 오버로딩</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">data class Point(val x: Int, val y: Int) {\n    operator fun plus(other: Point): Point {\n        return Point(x + other.x, y + other.y)\n    }\n}\n\nfun main() {\n    val p1 = Point(10, 20)\n    val p2 = Point(30, 40)\n    println(p1 + p2) // + 기호를 쓰면 plus 함수 호출\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>plus 함수 앞에 operator 키워드를 붙여야 한다.</li>\n<li>연산자를 확장 함수로 정의할 수도 있다.</li>\n</ul>\n<table>\n<thead>\n<tr>\n<th>표현식</th>\n<th>함수 이름</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>a + b</td>\n<td>plus</td>\n</tr>\n<tr>\n<td>a - b</td>\n<td>minus</td>\n</tr>\n<tr>\n<td>a * b</td>\n<td>times</td>\n</tr>\n<tr>\n<td>a / b</td>\n<td>div</td>\n</tr>\n<tr>\n<td>a % b</td>\n<td>mod</td>\n</tr>\n</tbody>\n</table>\n<ul>\n<li>연산자 우선순위는 표준 숫자 타입에 대한 연산자 우선순위와 같다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">operator fun Point.times(scale: Double): Point {\n    return Point((x * scale).toInt(), (y * scale).toInt())\n}\n\nfun main() {\n    val p = Point(10, 20)\n    println(p * 1.5)\n}</code>\n        </deckgo-highlight-code>\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\">operator fun Char.times(count: Int): String {\n    return toString().repeat(count)\n}\n\nfun main() {\n    println(&#39;a&#39; * 3)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>연산자 함수의 반환 타입이 꼭 두 피연산자 중 하나와 일치해야만 하는 것도 아니다.</li>\n</ul>\n<h3 id=\"-912-연산을-적용한-다음에-그-결과를-바로-대입-복합-대입-연산자-오버로딩\" style=\"position:relative;\"><a href=\"#-912-%EC%97%B0%EC%82%B0%EC%9D%84-%EC%A0%81%EC%9A%A9%ED%95%9C-%EB%8B%A4%EC%9D%8C%EC%97%90-%EA%B7%B8-%EA%B2%B0%EA%B3%BC%EB%A5%BC-%EB%B0%94%EB%A1%9C-%EB%8C%80%EC%9E%85-%EB%B3%B5%ED%95%A9-%EB%8C%80%EC%9E%85-%EC%97%B0%EC%82%B0%EC%9E%90-%EC%98%A4%EB%B2%84%EB%A1%9C%EB%94%A9\" aria-label=\" 912 연산을 적용한 다음에 그 결과를 바로 대입 복합 대입 연산자 오버로딩 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>🔖 9.1.2 연산을 적용한 다음에 그 결과를 바로 대입: 복합 대입 연산자 오버로딩</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    var point = Point(1, 2)\n    point += Point(3, 4)\n    println(point)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>plus와 같은 연산자를 오버로딩하면 복합 대입 연산자를 자동으로 지원한다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">operator fun &lt;T&gt; MutableCollection&lt;T&gt;.plusAssign(element: T) {\n    this.add(element)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>어떤 클래스가 plus, plusAssign을 모두 정의하고 +=을 사용하면 오류를 보고한다.</li>\n<li>코틀린 표준 라이브러리는 컬렉션에 대해 2가지 접근 방법을 제공\n<ul>\n<li>+,-는 항상 새로운 컬렉션 반환</li>\n<li>+=, -= 연산자는 항상 변경 가능한 컬렉션에 작용해 메모리에 있는 객체 상태를 변화</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-913-피연산자가-1개뿐인-연산자-단항-연산자-오버로딩\" style=\"position:relative;\"><a href=\"#-913-%ED%94%BC%EC%97%B0%EC%82%B0%EC%9E%90%EA%B0%80-1%EA%B0%9C%EB%BF%90%EC%9D%B8-%EC%97%B0%EC%82%B0%EC%9E%90-%EB%8B%A8%ED%95%AD-%EC%97%B0%EC%82%B0%EC%9E%90-%EC%98%A4%EB%B2%84%EB%A1%9C%EB%94%A9\" aria-label=\" 913 피연산자가 1개뿐인 연산자 단항 연산자 오버로딩 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>🔖 9.1.3 피연산자가 1개뿐인 연산자: 단항 연산자 오버로딩</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">operator fun Point.unaryMinus(): Point {\n    return Point(-x, -y)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>단항 연산자를 오버로딩하기 위해 사용하는 함수는 인자를 취하지 않는다.</li>\n</ul>\n<table>\n<thead>\n<tr>\n<th>표현식</th>\n<th>함수 이름</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>+a</td>\n<td>unaryPlus</td>\n</tr>\n<tr>\n<td>-a</td>\n<td>unaryMinus</td>\n</tr>\n<tr>\n<td>!a</td>\n<td>not</td>\n</tr>\n<tr>\n<td>a++, ++a</td>\n<td>inc</td>\n</tr>\n<tr>\n<td>a-- , --a</td>\n<td>dec</td>\n</tr>\n</tbody>\n</table>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    var bd = BigDecimal.ZERO\n    println(bd++) // 후위 증가 연산자는 println이 실행된 다음에 값 증가\n    println(bd)\n    println(++bd) // 전위 증가 연산자는 println이 실행되기 전에 값 증가\n}</code>\n        </deckgo-highlight-code>\n<h2 id=\"-92-비교-연산자를-오버로딩해서-객체들-사이의-관계를-쉽게-검사\" style=\"position:relative;\"><a href=\"#-92-%EB%B9%84%EA%B5%90-%EC%97%B0%EC%82%B0%EC%9E%90%EB%A5%BC-%EC%98%A4%EB%B2%84%EB%A1%9C%EB%94%A9%ED%95%B4%EC%84%9C-%EA%B0%9D%EC%B2%B4%EB%93%A4-%EC%82%AC%EC%9D%B4%EC%9D%98-%EA%B4%80%EA%B3%84%EB%A5%BC-%EC%89%BD%EA%B2%8C-%EA%B2%80%EC%82%AC\" aria-label=\" 92 비교 연산자를 오버로딩해서 객체들 사이의 관계를 쉽게 검사 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>📖 9.2 비교 연산자를 오버로딩해서 객체들 사이의 관계를 쉽게 검사</h2>\n<h3 id=\"-921-동등성-연산자-equals\" style=\"position:relative;\"><a href=\"#-921-%EB%8F%99%EB%93%B1%EC%84%B1-%EC%97%B0%EC%82%B0%EC%9E%90-equals\" aria-label=\" 921 동등성 연산자 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>🔖 9.2.1 동등성 연산자: equals</h3>\n<ul>\n<li>!= 연산자를 사용하는 식도 equals 호출로 컴파일 된다.</li>\n<li>null 검사도 한다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Point(val x: Int, val y: Int) {\n    override fun equals(other: Any?): Boolean {\n        if (other === this) return true\n        if (other !is Point) return false\n        return other.x == x &amp;&amp; other.y == y\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>동등성 비교 연산자(===)는 자바 == 연산자와 같다.\n<ul>\n<li>자신의 두 피연산자가 서로 같은 객체ㅡㄹ 가리키는지 비교한다.</li>\n</ul>\n</li>\n<li>===를 오버로딩할 수는 없다.</li>\n</ul>\n<h3 id=\"-922-순서-연산자-compareto----\" style=\"position:relative;\"><a href=\"#-922-%EC%88%9C%EC%84%9C-%EC%97%B0%EC%82%B0%EC%9E%90-compareto----\" aria-label=\" 922 순서 연산자 compareto     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>🔖 9.2.2 순서 연산자: compareTo (&#x3C;, >, &#x3C;=, >=)</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Person(val firstName: String, val lastName: String) : Comparable&lt;Person&gt; {\n    override fun compareTo(other: Person): Int {\n        return compareValuesBy(this, other, Person::lastName, Person::firstName)\n    }\n}\n\nfun main() {\n    val p1 = Person(&quot;Alice&quot;, &quot;Smith&quot;)\n    val p2 = Person(&quot;Bob&quot;, &quot;Johnson&quot;)\n    println(p1 &lt; p2)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>비교 연산자를 제공한다.</li>\n<li><code>compareValuesBy</code>는 두 객체와 여러 비교 함수를 인자로 받는다.\n<ul>\n<li>첫 번째 비교 함수에 두 객체를 넘겨 두 객체가 같지 않다는 결과가 나오면 그 결괏값을 즉시 반환</li>\n</ul>\n</li>\n<li>비교 연산자를 자바 클래스에 대해 사용하기 위해 특별히 확장 메서드를 만들거나 할 필요는 없다.</li>\n</ul>\n<h2 id=\"-93-컬렉션과-범위에-대해-쓸-수-있는-관례\" style=\"position:relative;\"><a href=\"#-93-%EC%BB%AC%EB%A0%89%EC%85%98%EA%B3%BC-%EB%B2%94%EC%9C%84%EC%97%90-%EB%8C%80%ED%95%B4-%EC%93%B8-%EC%88%98-%EC%9E%88%EB%8A%94-%EA%B4%80%EB%A1%80\" aria-label=\" 93 컬렉션과 범위에 대해 쓸 수 있는 관례 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>📖 9.3 컬렉션과 범위에 대해 쓸 수 있는 관례</h2>\n<h3 id=\"-931-인덱스로-원소-접근-get과-set\" style=\"position:relative;\"><a href=\"#-931-%EC%9D%B8%EB%8D%B1%EC%8A%A4%EB%A1%9C-%EC%9B%90%EC%86%8C-%EC%A0%91%EA%B7%BC-get%EA%B3%BC-set\" aria-label=\" 931 인덱스로 원소 접근 get과 set 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>🔖 9.3.1 인덱스로 원소 접근: get과 set</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">operator fun Point.get(index: Int): Int {\n    return when (index) {\n        0 -&gt; x\n        1 -&gt; y\n        else -&gt;\n            throw IndexOutOfBoundsException(&quot;Invalid coordinate $index&quot;)\n    }\n}\n\nfun main() {\n    val p = Point(10, 20)\n    println(p[1])\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>get 메서드의 파라미터로 Int가 아닌 타입도 사용할 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">data class MutablePoint(var x: Int, var y: Int)\n\noperator fun MutablePoint.set(index: Int, value: Int) {\n    when (index) {\n        0 -&gt; x = value\n        1 -&gt; y = value\n        else -&gt;\n            throw IndexOutOfBoundsException(&quot;Invalid coordinate $index&quot;)\n    }\n}\n\nfun main() {\n    val p = MutablePoint(10, 20)\n    p[1] = 42\n    println(p)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>set도 관례로 표현할 수 있다.</li>\n</ul>\n<h3 id=\"-932-어떤-객체가-컬렉션에-들어있는지-검사-in-관레\" style=\"position:relative;\"><a href=\"#-932-%EC%96%B4%EB%96%A4-%EA%B0%9D%EC%B2%B4%EA%B0%80-%EC%BB%AC%EB%A0%89%EC%85%98%EC%97%90-%EB%93%A4%EC%96%B4%EC%9E%88%EB%8A%94%EC%A7%80-%EA%B2%80%EC%82%AC-in-%EA%B4%80%EB%A0%88\" aria-label=\" 932 어떤 객체가 컬렉션에 들어있는지 검사 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>🔖 9.3.2 어떤 객체가 컬렉션에 들어있는지 검사: in 관레</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">data class Rectangle(val upperLeft: Point, val lowerRight: Point)\n\noperator fun Rectangle.contains(p: Point): Boolean {\n    return p.x in upperLeft.x..&lt;lowerRight.x &amp;&amp;\n            p.y in upperLeft.y..&lt;lowerRight.y // 열린 범위\n}\n\nfun main() {\n    val rect = Rectangle(Point(10, 20), Point(50, 50))\n    println(Point(20, 30) in rect)\n    println(Point(5, 5) in rect)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>..&#x3C; 연산자를 쓰면 열린 범위를 만들 수 있다.</li>\n<li>in 함수는 contains 메서드의 수신 객체가 되고 in의 왼쪽에 있는 객체는 contains 메서드에 인자로 전달된다.</li>\n</ul>\n<h3 id=\"-933-객체로부터-범위-만들기-rangeto와-rangeuntil-관레\" style=\"position:relative;\"><a href=\"#-933-%EA%B0%9D%EC%B2%B4%EB%A1%9C%EB%B6%80%ED%84%B0-%EB%B2%94%EC%9C%84-%EB%A7%8C%EB%93%A4%EA%B8%B0-rangeto%EC%99%80-rangeuntil-%EA%B4%80%EB%A0%88\" aria-label=\" 933 객체로부터 범위 만들기 rangeto와 rangeuntil 관레 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>🔖 9.3.3 객체로부터 범위 만들기: rangeTo와 rangeUntil 관레</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">operator fun &lt;T: Comparable&lt;T&gt;&gt; T.rangeTo(other: T): ClosedRange&lt;T&gt;</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린 표준 라이브러리에는 모든 Comparable 객체에 대해 적용 가능한 rangeTo 함수가 들어있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val now = LocalDate.now()\n    val vacation = now..now.plusDays(10)\n    println(now.plusWeeks(1) in vacation)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>now..now.plusDays(10)</code> 식은 컴파일러에 의해 <code>now.rangeTo(now.plusDays(10))</code>으로 변환된다.</li>\n<li>rangeTo 연산자는 다른 산술 연산자보다 우선순위가 낮다.\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\">fun main() {\n    val n = 9\n    (0..n).forEach { println(it) }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>범위의 메서드를 호출하려면 범위를 괄호로 둘러싸야 한다.</li>\n<li>rangeUntil 연산자(..&#x3C;)>=는 열린 범위를 만든다.</li>\n</ul>\n<h3 id=\"-934-자신의-타입에-대해-루프-수행-iterator-관례\" style=\"position:relative;\"><a href=\"#-934-%EC%9E%90%EC%8B%A0%EC%9D%98-%ED%83%80%EC%9E%85%EC%97%90-%EB%8C%80%ED%95%B4-%EB%A3%A8%ED%94%84-%EC%88%98%ED%96%89-iterator-%EA%B4%80%EB%A1%80\" aria-label=\" 934 자신의 타입에 대해 루프 수행 iterator 관례 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>🔖 9.3.4 자신의 타입에 대해 루프 수행: iterator 관례</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">operator fun CharSequence.iterator(): CharIterator</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\">operator fun ClosedRange&lt;LocalDate&gt;.iterator(): Iterator&lt;LocalDate&gt; =\n    object : Iterator&lt;LocalDate&gt; {\n        var current = start\n        override fun hasNext(): Boolean =\n            current &lt;= endInclusive\n        override fun next(): LocalDate {\n            val thisDate = current\n            current = current.plusDays(1)\n            return thisDate\n        }\n    }\n\nfun main() {\n    val newYear = LocalDate.ofYearDay(2042, 1)\n    val daysOff = newYear.minusDays(1)..newYear\n    for (dayOff in daysOff) {\n        println(dayOff)\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>ClosedRange&#x3C;LocalDate></code>에 대한 확장 함수 iterator를 정의했기 때문에 LocalDate의 범위 객체를 for 루프에 사용할 수 있다.</li>\n</ul>\n<h2 id=\"-94-component-함수를-사용해-구조-분해-선언-제공\" style=\"position:relative;\"><a href=\"#-94-component-%ED%95%A8%EC%88%98%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%B4-%EA%B5%AC%EC%A1%B0-%EB%B6%84%ED%95%B4-%EC%84%A0%EC%96%B8-%EC%A0%9C%EA%B3%B5\" aria-label=\" 94 component 함수를 사용해 구조 분해 선언 제공 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>📖 9.4 component 함수를 사용해 구조 분해 선언 제공</h2>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val p = Point(10, 20)\n    val (x, y) = p\n    println(x)\n    println(y)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>구조 분해 선언은 일반 변수 선언과 비슷해 보인다.</li>\n<li>내부에서 구조 분해 선언의 각 변수를 초기화하고자 componentN이라는 함수를 호출한다.\n<ul>\n<li>N은 구조 분해 선언에 있는 변수 위치에 따라 붙는 번호</li>\n</ul>\n</li>\n<li>data class의 주 생성자에 들어있는 프로퍼티에 대해서는 컴파일러가 자동으로 componentN 함수를 만들어준다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">data class NameComponents(val name: String, val extension: String)\n\nfun splitFileName(fullName: String): NameComponents {\n    val result = fullName.split(&#39;.&#39;, limit = 2)\n    return NameComponents(result[0], result[1])\n}\n\nfun main() {\n    val (name, ext) = splitFileName(&quot;example.kt&quot;)\n    println(name)\n    println(ext)\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\">data class NameComponents(val name: String, val extension: String)\n\nfun splitFileName(fullName: String): NameComponents {\n    val (name, extension) = fullName.split(&#39;.&#39;, limit = 2)\n    return NameComponents(name, extension)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>컬렉션에 대해 구조 분해 선언 사용이 가능하다.</li>\n</ul>\n<h3 id=\"-941-구조-분해-선언과-루프\" style=\"position:relative;\"><a href=\"#-941-%EA%B5%AC%EC%A1%B0-%EB%B6%84%ED%95%B4-%EC%84%A0%EC%96%B8%EA%B3%BC-%EB%A3%A8%ED%94%84\" aria-label=\" 941 구조 분해 선언과 루프 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>🔖 9.4.1 구조 분해 선언과 루프</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun printEntries(map: Map&lt;String, String&gt;) {\n    for ((key, value) in map) {\n        println(&quot;$key -&gt; $value&quot;)\n    }\n}\n\nfun main() {\n    val map = mapOf(&quot;Oracle&quot; to &quot;Java&quot;, &quot;JetBrains&quot; to &quot;Kotlin&quot;)\n    printEntries(map)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>맵에 대한 확장 함수로 iterator가 들어있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    map.forEach { (key, value) -&gt; println(&quot;$key -&gt; $value&quot;) }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>람다가 구조 분해 선언을 쓸 수 있다.</li>\n</ul>\n<h3 id=\"-942-_-문자를-사용해-구조-분해-값-무시\" style=\"position:relative;\"><a href=\"#-942-_-%EB%AC%B8%EC%9E%90%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%B4-%EA%B5%AC%EC%A1%B0-%EB%B6%84%ED%95%B4-%EA%B0%92-%EB%AC%B4%EC%8B%9C\" aria-label=\" 942 _ 문자를 사용해 구조 분해 값 무시 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>🔖 9.4.2 _ 문자를 사용해 구조 분해 값 무시</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">data class Person(val firstName: String, val lastName: String, val age: Int, val city: String)\n\nfun introducePerson(p: Person) {\n    val (firstName, lastName, age, city) = p\n    println(&quot;This is $firstName, aged $age.&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\">    val (firstName, lastName, age) = p</code>\n        </deckgo-highlight-code>\n<ul>\n<li>lastName을 그냥 없앨 수는 없다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun introducePerson(p: Person) {\n    val (firstName, _, age) = p\n    println(&quot;This is $firstName, aged $age.&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>_</code> 를 쓰면 컴포넌트를 무시하고 구조 분해 선언이 가능하다.</li>\n</ul>\n<h2 id=\"-95-프로퍼티-접근자-로직-재활용-위임-프로퍼티\" style=\"position:relative;\"><a href=\"#-95-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0-%EC%A0%91%EA%B7%BC%EC%9E%90-%EB%A1%9C%EC%A7%81-%EC%9E%AC%ED%99%9C%EC%9A%A9-%EC%9C%84%EC%9E%84-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0\" aria-label=\" 95 프로퍼티 접근자 로직 재활용 위임 프로퍼티 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>📖 9.5 프로퍼티 접근자 로직 재활용: 위임 프로퍼티</h2>\n<h3 id=\"-951-위임-프로퍼티의-기본-문법과-내부-동작\" style=\"position:relative;\"><a href=\"#-951-%EC%9C%84%EC%9E%84-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0%EC%9D%98-%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95%EA%B3%BC-%EB%82%B4%EB%B6%80-%EB%8F%99%EC%9E%91\" aria-label=\" 951 위임 프로퍼티의 기본 문법과 내부 동작 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>🔖 9.5.1 위임 프로퍼티의 기본 문법과 내부 동작</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Foo {\n    var p = Type by Delegate()\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>p 프로퍼티는 접근자 로직을 다른 객체에 위임한다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Foo {\n    private val delegate = Delegate()\n    \n    var p: Type\n        set(value: Type) = delegate.setValue(/**/, value)\n        get() = delegate.getValue(/**/)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>프로퍼티 위임 관례에 따라 Delegate 클래스는 get, set을 제공해야한다.</li>\n<li>by 키워드는 프로퍼티와 위임객체를 연결한다.</li>\n</ul>\n<h3 id=\"-952-위임-프로퍼티-사용-by-lazy를-사용한-지연-초기화\" style=\"position:relative;\"><a href=\"#-952-%EC%9C%84%EC%9E%84-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0-%EC%82%AC%EC%9A%A9-by-lazy%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%9C-%EC%A7%80%EC%97%B0-%EC%B4%88%EA%B8%B0%ED%99%94\" aria-label=\" 952 위임 프로퍼티 사용 by lazy를 사용한 지연 초기화 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>🔖 9.5.2 위임 프로퍼티 사용: by lazy()를 사용한 지연 초기화</h3>\n<ul>\n<li>지연 초기화는 객체의 일부분을 초기화하지 않고 남겨뒀다가 실제로 그 부분의 값이 필요할 경우 초기화할 때 쓰이는 패턴</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Person(val name: String) {\n    private var _emails: List&lt;String&gt;? = null\n\n    val emails: List&lt;String&gt;\n        get() {\n            if (_emails == null) {\n                _emails = loadEamils(this)\n            }\n            return _emails!!\n        }\n}\n\n\nfun main() {\n    val p = Person(&quot;Alice&quot;)\n    p.emails\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>뒷받침하는 프로퍼티 기법 사용</li>\n<li>클래스 같은 개념을 표헌하는 프로퍼티가 2개 있을 때 비공개 프로퍼티 앞에 밑줄을 붙이며, 공개 프로퍼티에는 아무것도 붙이지 않는다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Person(val name: String) {\n    val emails by lazy { loadEmails(this) }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>위임 프로퍼티를 사용하면 훨씬 간단해진다.</li>\n<li>lazy 함수는 기본적으로 스레드 안전하다.</li>\n</ul>\n<h3 id=\"-953-위임-프로퍼티-구현\" style=\"position:relative;\"><a href=\"#-953-%EC%9C%84%EC%9E%84-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0-%EA%B5%AC%ED%98%84\" aria-label=\" 953 위임 프로퍼티 구현 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>🔖 9.5.3 위임 프로퍼티 구현</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun interface Observer {\n    fun onChange(name: String, oldValue: Any?, newValue: Any?)\n}\n\nopen class Observable {\n    val observers = mutableListOf&lt;Observer&gt;()\n    fun notifyObservers(propName: String, oldValue: Any?, newValue: Any?) {\n        for (obs in observers) {\n            obs.onChange(propName, oldValue, newValue)\n        }\n    }\n}\n\nclass Person(val name: String, age: Int, salary: Int) : Observable() {\n    var age: Int = age\n        set(newValue) {\n            val oldValue = field\n            field = newValue\n            notifyObservers(&quot;age&quot;, oldValue, newValue)\n        }\n    var salary: Int = salary\n        set(newValue) {\n            val oldValue = field\n            field = newValue\n            notifyObservers(&quot;salary&quot;, oldValue, newValue)\n        }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>field 키워드를 사용해 age와 salary 프로퍼티를 뒷받침하는 필드에 접근하는 방법을 보여준다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class ObservableProperty(val propName: String, var propValue: Int, val observable: Observable) {\n    fun getValue(): Int = propValue\n    fun setValue(newValue: Int) {\n        val oldValue = propValue\n        propValue = newValue\n        observable.notifyObservers(propName, oldValue, newValue)\n    }\n}\n\nclass Person(val name: String, age: Int, salary: Int) : Observable() {\n    val _age = ObservableProperty(&quot;age&quot;, age, this)\n    var age: Int\n        get() = _age.getValue()\n        set(value) {\n            _age.setValue(value)\n        }\n    val _salary = ObservableProperty(&quot;salary&quot;, salary, this)\n    var salary: Int\n        get() = _salary.getValue()\n        set(value) {\n            _salary.setValue(value)\n        }\n}</code>\n        </deckgo-highlight-code>\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\">class ObservableProperty(var propValue: Int, val observable: Observable) {\n    operator fun getValue(thisRef: Any?, prop: KProperty&lt;*&gt;): Int = propValue\n    operator fun setValue(thisRef: Any?, prop: KProperty&lt;*&gt;, newValue: Int) {\n        val oldValue = propValue\n        propValue = newValue\n        observable.notifyObservers(prop.name, oldValue, newValue)\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>operator 변경자가 붙는다.</li>\n<li>KProperty 타입의 객체를 사용해 프로퍼티 표현</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Person(val name: String, age: Int, salary: Int) : Observable() {\n    val age by ObservableProperty(age, this)\n    var salary by ObservableProperty(salary, this)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>여러 작업을 컴파일러가 자동으로 처리해준다.</li>\n<li>by의 오른쪽에 있는 식이 꼭 새 인스턴스를 만들 필요는 없다.</li>\n</ul>\n<h3 id=\"-954-위임-프로퍼티는-커스텀-접근자가-있는-감춰진-프로퍼티로-변환된다\" style=\"position:relative;\"><a href=\"#-954-%EC%9C%84%EC%9E%84-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0%EB%8A%94-%EC%BB%A4%EC%8A%A4%ED%85%80-%EC%A0%91%EA%B7%BC%EC%9E%90%EA%B0%80-%EC%9E%88%EB%8A%94-%EA%B0%90%EC%B6%B0%EC%A7%84-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0%EB%A1%9C-%EB%B3%80%ED%99%98%EB%90%9C%EB%8B%A4\" aria-label=\" 954 위임 프로퍼티는 커스텀 접근자가 있는 감춰진 프로퍼티로 변환된다 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>🔖 9.5.4 위임 프로퍼티는 커스텀 접근자가 있는 감춰진 프로퍼티로 변환된다</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class C {\n    private val &lt;delegate&gt; = MyDelegate()\n    \n    var prop: Type\n        get() = &lt;delegate&gt;.getValue(this, &lt;property&gt;)\n        set(value: Type) = &lt;delegate&gt;.setValue(this, &lt;property&gt;, value)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>컴파일러는 모든 프로퍼티 접근자 안에 getValue, setValue 호출 코드를 생성해준다.</li>\n<li>프로퍼티 값이 저장될 장소를 바꿀 수도 있고 프로퍼티를 읽거나 쓸 때 벌어질 일을 변경할 수도 있다.</li>\n</ul>\n<h3 id=\"-955-맵에-위임해서-동적으로-애트리뷰트-접근\" style=\"position:relative;\"><a href=\"#-955-%EB%A7%B5%EC%97%90-%EC%9C%84%EC%9E%84%ED%95%B4%EC%84%9C-%EB%8F%99%EC%A0%81%EC%9C%BC%EB%A1%9C-%EC%95%A0%ED%8A%B8%EB%A6%AC%EB%B7%B0%ED%8A%B8-%EC%A0%91%EA%B7%BC\" aria-label=\" 955 맵에 위임해서 동적으로 애트리뷰트 접근 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>🔖 9.5.5 맵에 위임해서 동적으로 애트리뷰트 접근</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Person {\n    private val _attributes = mutableMapOf&lt;String, String&gt;()\n\n    fun setAttribute(attrName: String, value: String) {\n        _attributes[attrName] = value\n    }\n\n    var name: String\n        get() = _attributes[&quot;name&quot;]!!\n        set(value) {\n            _attributes[&quot;name&quot;] = value\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\">class Person {\n    private val _attributes = mutableMapOf&lt;String, String&gt;()\n\n    fun setAttribute(attrName: String, value: String) {\n        _attributes[attrName] = value\n    }\n\n    var name: String by _attributes\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>Map에 대해 getValue, setValue 확장 함수를 제공하기에 동작함.</li>\n<li>getValue에서 맵에 프로퍼티 값을 저장할 때는 자동으로 프로퍼티 이름을 키로 활용</li>\n</ul>\n<h3 id=\"-956-실전-프레임워크가-위임-프로퍼티를-활용하는-방법\" style=\"position:relative;\"><a href=\"#-956-%EC%8B%A4%EC%A0%84-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC%EA%B0%80-%EC%9C%84%EC%9E%84-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95\" aria-label=\" 956 실전 프레임워크가 위임 프로퍼티를 활용하는 방법 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>🔖 9.5.6 실전 프레임워크가 위임 프로퍼티를 활용하는 방법</h3>\n<ul>\n<li>위임 프로퍼티는 프로퍼티의 접근 로직을 재사용 가능하게 만들어, 코드의 중복을 줄이고 유지보수성을 향상시킨다.</li>\n<li>프레임워크나 라이브러리에서 공통된 프로퍼티 동작을 캡슐화하여, 사용자 코드의 간결함과 일관성을 유지할 수 있다.</li>\n</ul>","excerpt":"코틀린은 어떤 언어 기능과 미리 정해진 이름의 함수를 연결해주는 기법인 관례에 의존한다. 📖 9.1 산술 연산자를 오버로드해서 임의의 클래스에 대한 연산을 더 편리하게 만들기 🔖 9.1.1 plus, times, divide 등: 이항 산술 연산 오버로딩 plus 함수 앞에 operator 키워드를 붙여야 한다. 연산자를 확장 함수로 정의할 수도 있다. 표현식 함수 이름 a + b plus a - b minus a * b times a / b div a % b mod…","fields":{"slug":"/backend/kotlin-in-action/9장-연산자_오버로딩과_다른_관례/"},"frontmatter":{"title":"Kotlin in Action - 9장 연산자 오버로딩과 다른 관례","thumbnail":{"childImageSharp":{"fluid":{"src":"/static/f7f7ddfa31d1614405dc5af1487b9ec4/9c94d/kotlin-in-action.png"}}},"draft":false,"category":"Back-End","tags":["Kotlin"],"date":"April 27, 2025"}}}},"staticQueryHashes":["2374173507","2996537568","3691437124"]}