{"componentChunkName":"component---src-containers-post-index-tsx","path":"/backend/kotlin-in-action/4장-클래스_객체_인터페이스/","result":{"pageContext":{"next":{"id":"f3c5a39a-dd42-5db5-849f-06d2ef7e0de0","html":"<h2 id=\"-31-코틀린에서-컬렉션-만들기\" style=\"position:relative;\"><a href=\"#-31-%EC%BD%94%ED%8B%80%EB%A6%B0%EC%97%90%EC%84%9C-%EC%BB%AC%EB%A0%89%EC%85%98-%EB%A7%8C%EB%93%A4%EA%B8%B0\" aria-label=\" 31 코틀린에서 컬렉션 만들기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 3.1 코틀린에서 컬렉션 만들기</h2>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    fun main() {\n        val set = setOf(1, 7, 53)\n        val list = listOf(1, 7, 53)\n        val map = mapOf(1 to &quot;one&quot;, 7 to &quot;seven&quot;, 53 to &quot;fifty-three&quot;)\n        \n        println(set.javaClass)\n        println(list.javaClass)\n        println(map.javaClass)\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린은 표준 자바 컬렉션 클래스를 사용한다.\n<ul>\n<li>코틀린 컬렉션 인터페이스는 디폴트로 읽기 전용이다.</li>\n</ul>\n</li>\n<li>코틀린 컬렉션은 자바 컬렉션보다 더 많은 기능을 쓸 수 있다!\n<ul>\n<li>원소 뒤섞기 등</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"-32-함수를-호출하기-쉽게-만들기\" style=\"position:relative;\"><a href=\"#-32-%ED%95%A8%EC%88%98%EB%A5%BC-%ED%98%B8%EC%B6%9C%ED%95%98%EA%B8%B0-%EC%89%BD%EA%B2%8C-%EB%A7%8C%EB%93%A4%EA%B8%B0\" aria-label=\" 32 함수를 호출하기 쉽게 만들기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 3.2 함수를 호출하기 쉽게 만들기</h2>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    fun &lt;T&gt; joinToString(\n        collection: Collection&lt;T&gt;,\n        separator: String,\n        prefix: String,\n        postfix: String\n    ): String {\n        \n        val result = StringBuilder(prefix)\n        \n        for ((index, element) in collection.withIndex()) {\n            if (index &gt; 0) result.append(separator) // 첫 원소 앞에는 구분자를 붙이면 안된다.\n            result.append(element)\n        }\n        \n        result.append(postfix)\n        return result.toString()\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>덜 번잡하게 만들 수는 없을까?</li>\n</ul>\n<h3 id=\"-321-이름-붙인-인자\" style=\"position:relative;\"><a href=\"#-321-%EC%9D%B4%EB%A6%84-%EB%B6%99%EC%9D%B8-%EC%9D%B8%EC%9E%90\" aria-label=\" 321 이름 붙인 인자 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 3.2.1 이름 붙인 인자</h3>\n<p>자바의 일부 코딩스타일에서는 method 호출 시, 파라미터 이름을 주석에 넣으라고 요구하기도 한다.</p>\n<ul>\n<li>코틀린으로 작성한 함수를 호출할 때는 함수에 전달하는 인자 중 일부(또는 전부)의 이름을 명시할 수 있다.\n<ul>\n<li>모든 인자의 이름을 지정한다면 인자 순서도 변경 가능하다!</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-322-디폴트-파라미터-값\" style=\"position:relative;\"><a href=\"#-322-%EB%94%94%ED%8F%B4%ED%8A%B8-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0-%EA%B0%92\" aria-label=\" 322 디폴트 파라미터 값 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 3.2.2 디폴트 파라미터 값</h3>\n<p>자바에서는 일부 클래스에서 오버로딩한 메서드가 너무 많아질 수 있다.</p>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    fun &lt;T&gt; joinToString(\n        collection: Collection&lt;T&gt;,\n        separator: String = &quot;, &quot;,\n        prefix: String = &quot;&quot;,\n        postfix: String = &quot;&quot;\n    ): String</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린에서는 함수 선언에서 파라미터의 기본값을 지정할 수 있어, 오버로딩을 상당히 피할 수 있다.</li>\n<li>함수의 디폴트 파라미터 값은 함수를 호출하는 쪽이 아니라 함수 선언쪽에 인코딩된다.</li>\n</ul>\n<h3 id=\"-323-정적인-유틸리티-클래스-없애기-최상위-함수와-프로퍼티\" style=\"position:relative;\"><a href=\"#-323-%EC%A0%95%EC%A0%81%EC%9D%B8-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%97%86%EC%95%A0%EA%B8%B0-%EC%B5%9C%EC%83%81%EC%9C%84-%ED%95%A8%EC%88%98%EC%99%80-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0\" aria-label=\" 323 정적인 유틸리티 클래스 없애기 최상위 함수와 프로퍼티 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 3.2.3 정적인 유틸리티 클래스 없애기: 최상위 함수와 프로퍼티</h3>\n<ul>\n<li>코틀린에서는 함수를 모든 다른 클래스의 밖에 위치시키면 된다.\n<ul>\n<li>함수들은 여전히 그 파일의 맨 앞에 정의된 패키지의 멤버 함수이므로 다른 패키지에서 그 함수를 사용하고 싶을 때는 그 함수가 정의된 패키지를 임포트해야만 한다.</li>\n<li>클래스이름을 내포하지 않아도 된다.</li>\n</ul>\n</li>\n<li>코틀린 컴파일러가 생성하는 클래스의 이름이 최상위 함수가 들어있던 코틀린 소스파일의 이름과 대응한다.\n<ul>\n<li><code>join.kt</code> -> <code>JoinKt</code></li>\n</ul>\n</li>\n</ul>\n<h4 id=\"최상위-프로퍼티\" style=\"position:relative;\"><a href=\"#%EC%B5%9C%EC%83%81%EC%9C%84-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0\" aria-label=\"최상위 프로퍼티 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>최상위 프로퍼티</h4>\n<ul>\n<li>함수와 마찬가지로 프로퍼티도 파일 최상위 수준에 놓을 수 있다.</li>\n<li>상수와 변수 모두 설정가능하다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">var opCount = 0\nval UNIX_LINE_SEPARATOR = &quot;\\n&quot;\nconst val UNIX_LINE_SEPARATOR = &quot;\\n&quot; // java code에 public static final 필드로 노출하고 싶다면 const 변경자 추가</code>\n        </deckgo-highlight-code>\n<h2 id=\"-33-메서드를-다른-클래스에-추가-확장-함수와-확장-프로퍼티\" style=\"position:relative;\"><a href=\"#-33-%EB%A9%94%EC%84%9C%EB%93%9C%EB%A5%BC-%EB%8B%A4%EB%A5%B8-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%97%90-%EC%B6%94%EA%B0%80-%ED%99%95%EC%9E%A5-%ED%95%A8%EC%88%98%EC%99%80-%ED%99%95%EC%9E%A5-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0\" aria-label=\" 33 메서드를 다른 클래스에 추가 확장 함수와 확장 프로퍼티 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 3.3 메서드를 다른 클래스에 추가: 확장 함수와 확장 프로퍼티</h2>\n<p>확장 함수</p>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun String.lastChar(): Char = this.get(this.length - 1)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>어떤 클래스의 멤버 메서드인 것처럼 호출할 수 있지만 그 클래스 밖에 선언된 함수</li>\n<li>수신 객체 타입: 확장이 정의될 클래스의 타입</li>\n<li>수신 객체: 호출하는 대상 값(객체)</li>\n</ul>\n<h3 id=\"-331-임포트와-확장-함수\" style=\"position:relative;\"><a href=\"#-331-%EC%9E%84%ED%8F%AC%ED%8A%B8%EC%99%80-%ED%99%95%EC%9E%A5-%ED%95%A8%EC%88%98\" aria-label=\" 331 임포트와 확장 함수 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 3.3.1 임포트와 확장 함수</h3>\n<ul>\n<li>확장 함수를 쓰려면 다른 클래스나 함수와 마찬가지로 해당 함수를 임포트해야만 한다.\n<ul>\n<li>이름 충돌을 막기 위함</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">import strings.lastChar as last\n\nval c = &quot;Kotlin&quot;.last()</code>\n        </deckgo-highlight-code>\n<ul>\n<li>as 키워드를 사용하면 다른 이름으로 부를 수 있다.</li>\n<li>확장 함수는 코틀린 문법상 반드시 짧은 이름을 써야 한다.</li>\n</ul>\n<h3 id=\"-332-자바에서-확장-함수-호출\" style=\"position:relative;\"><a href=\"#-332-%EC%9E%90%EB%B0%94%EC%97%90%EC%84%9C-%ED%99%95%EC%9E%A5-%ED%95%A8%EC%88%98-%ED%98%B8%EC%B6%9C\" aria-label=\" 332 자바에서 확장 함수 호출 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 3.3.2 자바에서 확장 함수 호출</h3>\n<ul>\n<li>확장 함수를 호출해도 다른 어댑터 객체나 실행 시점 부가 비용이 들지 않는다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">char c = StringUtilKt.lastChar(&quot;Java&quot;);</code>\n        </deckgo-highlight-code>\n<ul>\n<li>확장 함수가 StringUtil.kt 파일에 정의했다고 가정하면 자바에서 위와 같이 호출 가능하다.</li>\n</ul>\n<h3 id=\"-333-확장-함수로-유틸리티-함수-정의\" style=\"position:relative;\"><a href=\"#-333-%ED%99%95%EC%9E%A5-%ED%95%A8%EC%88%98%EB%A1%9C-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%95%A8%EC%88%98-%EC%A0%95%EC%9D%98\" aria-label=\" 333 확장 함수로 유틸리티 함수 정의 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 3.3.3 확장 함수로 유틸리티 함수 정의</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun &lt;T&gt; Collection&lt;T&gt;.joinToString( // Collection&lt;T&gt;에 대한 확장 함수 선언\n    separator: String = &quot;, &quot;,\n    prefix: String = &quot;&quot;,\n    postfix: String = &quot;&quot;\n): String {\n    val result = StringBuilder(prefix)\n\n    for ((index, element) in this.withIndex()) {\n        if (index &gt; 0) result.append(separator)\n        result.append(element)\n    }\n\n    result.append(postfix)\n    return result.toString()\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>joinToString</code>을 클래스의 멤버인 것처럼 호출할 수 있다.</li>\n<li>더 구체적인 타입을 수신 객체 타입으로 지정할 수도 있다.</li>\n</ul>\n<h3 id=\"-334-확장-함수는-오버라이드할-수-없다\" style=\"position:relative;\"><a href=\"#-334-%ED%99%95%EC%9E%A5-%ED%95%A8%EC%88%98%EB%8A%94-%EC%98%A4%EB%B2%84%EB%9D%BC%EC%9D%B4%EB%93%9C%ED%95%A0-%EC%88%98-%EC%97%86%EB%8B%A4\" aria-label=\" 334 확장 함수는 오버라이드할 수 없다 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 3.3.4 확장 함수는 오버라이드할 수 없다</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun View.showOff() = println(&quot;I&#39;m a view&quot;)\nfun Button.showOff() = println(&quot;I&#39;m a button&quot;)\n\nfun main() {\n    val view: View = Button()\n    view.showOff() // 확장함수는 정적으로 결정된다.\n    // I&#39;m a view\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>확장 함수는 클래스의 일부가 아니다.</li>\n<li>즉, 코틀린은 호출될 확장 함수를 정적으로 결정하기 때문에 오버라이딩이 적용되지 않는다.</li>\n</ul>\n<h3 id=\"-335-확장-프로퍼티\" style=\"position:relative;\"><a href=\"#-335-%ED%99%95%EC%9E%A5-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0\" aria-label=\" 335 확장 프로퍼티 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 3.3.5 확장 프로퍼티</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val String.lastChar: Char\n    get() = get(length - 1)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>확장 프로퍼티 또한 단지 수신 객체 클래스가 추가됐을 뿐이다.</li>\n<li>뒷받침하는 필드가 없어 기본 게터 구현을 제공할 수 없으므로 꼭 게터는 정의해야 한다.</li>\n<li>확장 프로퍼티를 사용하는 방법은 멤버 프로퍼티를 사용하는 방법과 같다.</li>\n</ul>\n<h2 id=\"-34-컬렉션-처리-가변-길이-인자-중위-함수-호출-라이브러리-지원\" style=\"position:relative;\"><a href=\"#-34-%EC%BB%AC%EB%A0%89%EC%85%98-%EC%B2%98%EB%A6%AC-%EA%B0%80%EB%B3%80-%EA%B8%B8%EC%9D%B4-%EC%9D%B8%EC%9E%90-%EC%A4%91%EC%9C%84-%ED%95%A8%EC%88%98-%ED%98%B8%EC%B6%9C-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%A7%80%EC%9B%90\" aria-label=\" 34 컬렉션 처리 가변 길이 인자 중위 함수 호출 라이브러리 지원 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 3.4 컬렉션 처리: 가변 길이 인자, 중위 함수 호출, 라이브러리 지원</h2>\n<ul>\n<li>vararg 키워드를 사용하면 호출 시 인자 개수가 달라질 수 있는 함수를 정의할 수 있다.</li>\n<li>중위 함수 호출 구문을 사용하면 인자가 하나뿐인 메서드를 간편하게 호출할 수 있다.</li>\n<li>구조 분해 선언을 사용하면 복합적인 값을 분해해서 여러 변수에 나눠 담을 수 있다.</li>\n</ul>\n<h3 id=\"-341-자바-컬렉션-api-확장\" style=\"position:relative;\"><a href=\"#-341-%EC%9E%90%EB%B0%94-%EC%BB%AC%EB%A0%89%EC%85%98-api-%ED%99%95%EC%9E%A5\" aria-label=\" 341 자바 컬렉션 api 확장 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 3.4.1 자바 컬렉션 API 확장</h3>\n<ul>\n<li>코틀린 표준 라이브러리는 수많은 확장 함수를 포함하고 있다.\n<ul>\n<li>last sum 등</li>\n</ul>\n</li>\n<li>코틀린 파일에서 디폴트로 임포트 된다.</li>\n</ul>\n<h3 id=\"-342-가변-인자-함수-인자의-개수가-달라질-수-있는-함수-정의\" style=\"position:relative;\"><a href=\"#-342-%EA%B0%80%EB%B3%80-%EC%9D%B8%EC%9E%90-%ED%95%A8%EC%88%98-%EC%9D%B8%EC%9E%90%EC%9D%98-%EA%B0%9C%EC%88%98%EA%B0%80-%EB%8B%AC%EB%9D%BC%EC%A7%88-%EC%88%98-%EC%9E%88%EB%8A%94-%ED%95%A8%EC%88%98-%EC%A0%95%EC%9D%98\" aria-label=\" 342 가변 인자 함수 인자의 개수가 달라질 수 있는 함수 정의 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 3.4.2 가변 인자 함수: 인자의 개수가 달라질 수 있는 함수 정의</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">public fun &lt;T&gt; listOf(vararg elements: T): List&lt;T&gt; = if (elements.size &gt; 0) elements.asList() else emptyList()</code>\n        </deckgo-highlight-code>\n<ul>\n<li>원하는 개수만큼 여러 값을 인자로 넘기면 배열에 그 값들을 넣어주는 언어 기능인 varargs를 사용</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main(args: Array&lt;String&gt;) {\n    val list = listOf(&quot;args: &quot;, *args)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린에서는 배열을 명시적으로 풀어 전달해줘야 한다.\n<ul>\n<li>스프레드 연산: 배열 앞에 * 붙이기</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-343-쌍튜플-다루기-중위-호출과-구조-분해-선언\" style=\"position:relative;\"><a href=\"#-343-%EC%8C%8D%ED%8A%9C%ED%94%8C-%EB%8B%A4%EB%A3%A8%EA%B8%B0-%EC%A4%91%EC%9C%84-%ED%98%B8%EC%B6%9C%EA%B3%BC-%EA%B5%AC%EC%A1%B0-%EB%B6%84%ED%95%B4-%EC%84%A0%EC%96%B8\" aria-label=\" 343 쌍튜플 다루기 중위 호출과 구조 분해 선언 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 3.4.3 쌍(튜플) 다루기: 중위 호출과 구조 분해 선언</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val map = mapOf(1 to &quot;one&quot;, 2 to &quot;two&quot;, 3 to &quot;three&quot;)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>to라는 단어는 코틀린 키워드가 아니다. 중위 호출(infix call) 방식으로 to 라는 일반 메서드를 호출한 것이다.</li>\n<li>중위 호출 시에는 수신 객체 뒤에 메서드 이름을 위치시키고 그 뒤에 유일한 메서드 인자를 넣는다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">infix fun Any.to(other: Any): Pair(this, other)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>함수를 중위 호출에 사용하게 허용하고 싶으면 infix 변경자를 함수 선언 앞에 추가해야 한다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val (number, name) = 1 to &quot;one&quot;</code>\n        </deckgo-highlight-code>\n<ul>\n<li>위와 같은 기능을 구조 분해 선언(destructuring declaration)이라고 부른다.</li>\n</ul>\n<h2 id=\"-35-문자열과-정규식-다루기\" style=\"position:relative;\"><a href=\"#-35-%EB%AC%B8%EC%9E%90%EC%97%B4%EA%B3%BC-%EC%A0%95%EA%B7%9C%EC%8B%9D-%EB%8B%A4%EB%A3%A8%EA%B8%B0\" aria-label=\" 35 문자열과 정규식 다루기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 3.5 문자열과 정규식 다루기</h2>\n<h3 id=\"-351-문자열-나누기\" style=\"position:relative;\"><a href=\"#-351-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%82%98%EB%88%84%EA%B8%B0\" aria-label=\" 351 문자열 나누기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 3.5.1 문자열 나누기</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    println(&quot;12.345-6.A&quot;.split(&quot;\\\\.|-&quot;.toRegex()))\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린에서는 split 함수에 전달하는 값의 타입에 따라 정규식이나 일반 텍스트 중 어느 것으로 분리하는지 쉽게 알 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    println(&quot;12.345-6.A&quot;.split(&#39;.&#39;, &#39;-&#39;))\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>여러 문자를 받을 수 있는 확장 함수도 있다.</li>\n</ul>\n<h3 id=\"-352-정규식과-3중-따옴표로-묶은-문자열\" style=\"position:relative;\"><a href=\"#-352-%EC%A0%95%EA%B7%9C%EC%8B%9D%EA%B3%BC-3%EC%A4%91-%EB%94%B0%EC%98%B4%ED%91%9C%EB%A1%9C-%EB%AC%B6%EC%9D%80-%EB%AC%B8%EC%9E%90%EC%97%B4\" aria-label=\" 352 정규식과 3중 따옴표로 묶은 문자열 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 3.5.2 정규식과 3중 따옴표로 묶은 문자열</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun parsePath(path: String) {\n    val directory = path.substringBeforeLast(&quot;/&quot;)\n    val fullName = path.substringAfterLast(&quot;/&quot;)\n    val fileName = fullName.substringBeforeLast(&quot;.&quot;)\n    val extension = fullName.substringAfterLast(&quot;.&quot;)\n    \n    println(&quot;Dir: $directory, name: $fileName, ext: $extension&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>정규식을 사용하지 않고도 문자열을 쉽게 파싱할 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun parsePathRegax(path: String) {\n    val regex = &quot;&quot;&quot;(.+)/(.+)\\.(.+)&quot;&quot;&quot;.toRegex()\n    val matchResult = regex.matchEntire(path)\n    if (matchResult != null) {\n        val (directory, filename, extension) = matchResult.destructured\n        println(&quot;Dir: $directory, name: $fileName, ext: $extension&quot;)\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>정규식을 활용하여 파싱할 수 있다.</li>\n<li>3중 따옴표 문자열에서는 \\를 포함한 어떤 문자도 이스케이프할 필요가 없다.</li>\n<li>destructured 프로퍼티: 그룹별로 분해한 매치 결과를 의미</li>\n</ul>\n<h3 id=\"-353-여러-줄-3중-따옴표-문자열\" style=\"position:relative;\"><a href=\"#-353-%EC%97%AC%EB%9F%AC-%EC%A4%84-3%EC%A4%91-%EB%94%B0%EC%98%B4%ED%91%9C-%EB%AC%B8%EC%9E%90%EC%97%B4\" aria-label=\" 353 여러 줄 3중 따옴표 문자열 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 3.5.3 여러 줄 3중 따옴표 문자열</h3>\n<ul>\n<li>3중 따옴표를 쓰면 줄 바꿈이 들어있는 텍스트를 쉽게 포함시킬 수 있다.</li>\n<li>들여쓰기도 모두 포함된다.</li>\n<li>문자열 템플릿을 사용할 수도 있다.</li>\n<li><code>trimIndent</code> 확장 함수를 호출하면 문자열의 모든 줄에서 가장 짧은 공통 들여쓰기를 찾아 각 줄의 첫 부분에서 제거하고, 공백만으로 이뤄진 첫 번째 줄과 마지막 줄을 제거해준다.</li>\n<li>여러 줄 문자열은 테스트에도 유용하다.</li>\n</ul>\n<h2 id=\"-36-코드-깔끔하게-다듬기-로컬-함수와-확장\" style=\"position:relative;\"><a href=\"#-36-%EC%BD%94%EB%93%9C-%EA%B9%94%EB%81%94%ED%95%98%EA%B2%8C-%EB%8B%A4%EB%93%AC%EA%B8%B0-%EB%A1%9C%EC%BB%AC-%ED%95%A8%EC%88%98%EC%99%80-%ED%99%95%EC%9E%A5\" aria-label=\" 36 코드 깔끔하게 다듬기 로컬 함수와 확장 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 3.6 코드 깔끔하게 다듬기: 로컬 함수와 확장</h2>\n<p>DRY: Don't Repeat Yourself(반복하지 말라)</p>\n<ul>\n<li>코틀린에서는 깔끔하게 코드를 조직할 수 있는 방법이 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class User(val id: Int, val name: String, val address: String)\n\nfun saveUser(user: User) {\n    if (user.name.isEmpty()) {\n        throw IllegalArgumentException(&quot;Can&#39;t save user ${user.id}: empty name&quot;)\n    }\n    if (user.address.isEmpty()) {\n        throw IllegalArgumentException(&quot;Can&#39;t save user ${user.id}: empty address&quot;)\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코드 중복을 보여주는 예제이다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun saveUser(user: User) {\n    fun validate(user: User, value: String, fieldName: String) {\n        if (value.isEmpty()) {\n            throw IllegalArgumentException(&quot;Can&#39;t save user ${user.id}: empty $fieldName&quot;)\n        }\n    }\n    validate(user, user.name, &quot;Name&quot;)\n    validate(user, user.address, &quot;Address&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>조금 나아졌다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class User(val id: Int, val name: String, val address: String)\n\nfun saveUser(user: User) {\n    fun validate(value: String, fieldName: String) {\n        if (value.isEmpty()) {\n            throw IllegalArgumentException(&quot;Can&#39;t save user ${user.id}: &quot; + &quot;empty $fieldName&quot;)\n        }\n    }\n    validate(user.name, &quot;Name&quot;)\n    validate(user.address, &quot;Address&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>바깥 함수의 파라미터에 직접 접근할 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class User(val id: Int, val name: String, val address: String)\n\nfun User.validateBeforeSave() {\n    fun validate(value: String, fieldName: String) {\n        if (value.isEmpty()) {\n            throw IllegalArgumentException(&quot;Can&#39;t save user ${id}: empty $fieldName&quot;)\n        }\n    }\n    validate(name, &quot;Name&quot;)\n    validate(address, &quot;Address&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>확장함수로 추출하기</li>\n<li>확장함수를 로컬 함수로 정의할 수도 있다. 다만, 내포된 함수의 깊이가 깊어지면 읽기가 어려워 일반적으로 한 단계만 함수를 내포시키라고 권장한다.</li>\n</ul>","excerpt":"📖 3.1 코틀린에서 컬렉션 만들기 코틀린은 표준 자바 컬렉션 클래스를 사용한다. 코틀린 컬렉션 인터페이스는 디폴트로 읽기 전용이다. 코틀린 컬렉션은 자바 컬렉션보다 더 많은 기능을 쓸 수 있다! 원소 뒤섞기 등 📖 3.2 함수를 호출하기 쉽게 만들기 덜 번잡하게 만들 수는 없을까? 🔖 3.2.1 이름 붙인 인자 자바의 일부 코딩스타일에서는 method…","fields":{"slug":"/backend/kotlin-in-action/3장-함수_정의와_호출/"},"frontmatter":{"title":"Kotlin in Action - 3장 함수 정의와 호출","thumbnail":{"childImageSharp":{"fluid":{"src":"/static/f7f7ddfa31d1614405dc5af1487b9ec4/9c94d/kotlin-in-action.png"}}},"draft":false,"category":"Back-End","tags":["Kotlin"],"date":"March 16, 2025"}},"previous":{"id":"73ef80cc-f46a-58a8-bc78-d9a5c897fe4c","html":"<ul>\n<li>람다는 기본적으로 다른 함수에 넘길 수 있는 작은 코드 조각을 의미</li>\n</ul>\n<h2 id=\"-51-람다식과-멤버-참조\" style=\"position:relative;\"><a href=\"#-51-%EB%9E%8C%EB%8B%A4%EC%8B%9D%EA%B3%BC-%EB%A9%A4%EB%B2%84-%EC%B0%B8%EC%A1%B0\" aria-label=\" 51 람다식과 멤버 참조 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>📖 5.1 람다식과 멤버 참조</h2>\n<h3 id=\"-511-람다-소개-코드-블록을-값으로-다루기\" style=\"position:relative;\"><a href=\"#-511-%EB%9E%8C%EB%8B%A4-%EC%86%8C%EA%B0%9C-%EC%BD%94%EB%93%9C-%EB%B8%94%EB%A1%9D%EC%9D%84-%EA%B0%92%EC%9C%BC%EB%A1%9C-%EB%8B%A4%EB%A3%A8%EA%B8%B0\" aria-label=\" 511 람다 소개 코드 블록을 값으로 다루기 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>🔖 5.1.1 람다 소개: 코드 블록을 값으로 다루기</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">button.setOnClickListener(object: OnClickListener {\n    override fun onClick(v: View) {\n        println(&quot;I was clicked!&quot;)\n    }\n})</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">button.setOnClickListener {\n    println(&quot;I was clicked!&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>람다를 메서드가 하나뿐인 익명 객체 대신 사용할 수 있다.</li>\n</ul>\n<h3 id=\"-512-람다와-컬렉션\" style=\"position:relative;\"><a href=\"#-512-%EB%9E%8C%EB%8B%A4%EC%99%80-%EC%BB%AC%EB%A0%89%EC%85%98\" aria-label=\" 512 람다와 컬렉션 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>🔖 5.1.2 람다와 컬렉션</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun findTheOldest(people: List&lt;Person&gt;) {\n    var maxAge = 0\n    var theOldest: Person? = null\n    for (person in people) {\n        if (person.age &gt; maxAge) {\n            maxAge = person.age\n            theOldest = person\n        }\n    }\n    println(theOldest)\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    people.maxByOrNull { it.age }</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>maxByOrNull</code> 함수를 이용하면 편한다.</li>\n<li>람다가 인자를 하나만 받고 그 인자에 구체적인 이름을 붙이고 싶지 않기 때문에 it이라는 암시적 이름을 사용한다.</li>\n<li>멤버 참조 또한 사용할 수 있다.</li>\n</ul>\n<h3 id=\"-513-람다식의-문법\" style=\"position:relative;\"><a href=\"#-513-%EB%9E%8C%EB%8B%A4%EC%8B%9D%EC%9D%98-%EB%AC%B8%EB%B2%95\" aria-label=\" 513 람다식의 문법 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>🔖 5.1.3 람다식의 문법</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val sum = {x: Int, y: Int -&gt; x + y}\n    println(sum)\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 main() {\n    { println(42) }\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 main() {\n    run{ println(42) }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>run은 인자로 받은 람다를 실행해 주는 라이브러리 함수</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    people.maxByOrNull({p: Person -&gt; p.age })</code>\n        </deckgo-highlight-code>\n<ul>\n<li>구분자가 너무 많이 쓰여서 가독성이 덜어진다.</li>\n<li>컴파일러가 문맥으로부터 유추할 수 있는 인자 타입을 굳이 적을 필요가 없다.</li>\n<li>인자가 하나뿐인 경우 이름을 붙이지 않아도 된다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    people.maxByOrNull() {p: Person -&gt; p.age }</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\">    people.maxByOrNull {p: Person -&gt; p.age }</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 people = listOf(Person(&quot;Dmitry&quot;, 4), Person(&quot;Eve&quot;, 4))\n    val names = people.joinToString(\n        separator = &quot; &quot;,\n        transform = { p: Person -&gt; p.name }\n    )\n    println(names)\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    people.joinToString(&quot; &quot;) { p: Person -&gt; p.name  }</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\">    people.maxByOrNull { p: Person -&gt; p.age }\n    people.maxByOrNull { p -&gt; p.age } // 파라미터 타입을 컴파일러가 추론</code>\n        </deckgo-highlight-code>\n<ul>\n<li>로컬 변수처럼 컴파일러는 람다 파라미터의 타입도 추론할 수 있다.</li>\n<li>it을 너무 남용하는 것보다는 파라미터를 명시하는 편이 낫다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    val getAge = { p: Person -&gt; p.age }\n    people.maxByOrNull { getAge}</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 sum = { x: Int, y: Int -&gt; \n        println(&quot;Computing $x and $y&quot;)\n        x + y\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>본문이 여러 줄로 이뤄진 경우 본문의 맨 마지막에 있는 식이 람다의 결괏값이 된다.</li>\n<li>명시적인 return이 필요하지 않다.</li>\n</ul>\n<h3 id=\"-514-현재-영역에-있는-변수-접근\" style=\"position:relative;\"><a href=\"#-514-%ED%98%84%EC%9E%AC-%EC%98%81%EC%97%AD%EC%97%90-%EC%9E%88%EB%8A%94-%EB%B3%80%EC%88%98-%EC%A0%91%EA%B7%BC\" aria-label=\" 514 현재 영역에 있는 변수 접근 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>🔖 5.1.4 현재 영역에 있는 변수 접근</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun printMessagesWithPrefix(messages: Collection&lt;String&gt;, prefix: String) {\n    messages.forEach { \n        println(&quot;$prefix $it&quot;)\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>forEach</code> 람다는 자신을 둘러싼 영역에 정의된 prefix 변수와 다른 변수에 접근할 수 있다.\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 printProblemCounts(responses: Collection&lt;String&gt;) {\n    var clientErrors = 0\n    var serverErrors = 0\n    responses.forEach {\n        if (it.startsWith(&quot;4&quot;)) {\n            clientErrors++\n        } else if (it.startsWith(&quot;5&quot;)) {\n            serverErrors++\n        }\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린과 자바 람다의 다른 점 중 한가지는 코틀린 람다 안에서는 파이널 변수가 아닌 변수에 접근할 수 있다는 점이다.</li>\n<li>람다 안에서 접근할 수 있는 외부 변수를 <strong>람다가 캡처한 변수</strong>라고 부른다.</li>\n<li>기본적으로 함수 안에 정의된 로컬 변수의 생명주기는 함수가 반환되면 끝난다.</li>\n<li>파이널 변수 캡처 -> 람다 코드를 변수 값과 함께 저장</li>\n<li>파이널이 아닌 변수를 캡처 -> 변수를 특별한 래퍼로 감싸서 나중에 변경하거나 읽을 수 있게 한 다음, 래퍼에 대한 참조를 람다 코드와 함께 저장</li>\n</ul>\n<h3 id=\"-515-멤버-참조\" style=\"position:relative;\"><a href=\"#-515-%EB%A9%A4%EB%B2%84-%EC%B0%B8%EC%A1%B0\" aria-label=\" 515 멤버 참조 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>🔖 5.1.5 멤버 참조</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    val getAge = Person::age</code>\n        </deckgo-highlight-code>\n<ul>\n<li>::을 사용하는 식을 멤버 참조라고 부른다.\n<ul>\n<li>한 메서드를 호출하거나 한 프로퍼티에 접근하는 함수 값을 만들어준다.</li>\n</ul>\n</li>\n<li>참조 대상이 함수인지 프로퍼티인지와는 관계없이 멤버 참조 뒤에는 괄호를 넣으면 안 된다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun salute() = println(&quot;Salute&quot;)\n\nfun main() {\n    run { ::salute }\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 createPerson = ::Person\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>생성자 참조를 사용하면 클래스 생성 작업을 연기하거나 저장해둘 수 있다.</li>\n<li>확장 함수도 똑같은 방식으로 참조할 수 있다.</li>\n</ul>\n<h3 id=\"-516-값과-엮인-호출-가능-참조\" style=\"position:relative;\"><a href=\"#-516-%EA%B0%92%EA%B3%BC-%EC%97%AE%EC%9D%B8-%ED%98%B8%EC%B6%9C-%EA%B0%80%EB%8A%A5-%EC%B0%B8%EC%A1%B0\" aria-label=\" 516 값과 엮인 호출 가능 참조 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>🔖 5.1.6 값과 엮인 호출 가능 참조</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val seb = Person(&quot;Sebastian&quot;, 26)\n    val personsAgeFunction = Person::age // 사람이 주어지면 나이를 돌려주는 멤버 참조\n    println(personsAgeFunction(seb)) // 사람을 인자로 받음\n    \n    val sebsAgeFunction = seb::age // 특정 사람의 나이를 돌려주는, 값과 엮인 호출 가능 참조\n    println(sebsAgeFunction) // 파라미터 지정하지 않아도 됨\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>특정 객체 인스턴스에 대한 메서드 호출에 대한 참조를 만들 수 있다.</li>\n</ul>\n<h2 id=\"-52-자바의-함수형-인터페이스-사용-단일-추상-메서드\" style=\"position:relative;\"><a href=\"#-52-%EC%9E%90%EB%B0%94%EC%9D%98-%ED%95%A8%EC%88%98%ED%98%95-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EC%82%AC%EC%9A%A9-%EB%8B%A8%EC%9D%BC-%EC%B6%94%EC%83%81-%EB%A9%94%EC%84%9C%EB%93%9C\" aria-label=\" 52 자바의 함수형 인터페이스 사용 단일 추상 메서드 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>📖 5.2 자바의 함수형 인터페이스 사용: 단일 추상 메서드</h2>\n<p>함수형 인터페이스 or 단일 추상 메서드 인터페이스</p>\n<ul>\n<li>인터페이스 안에 추상 메서드가 단 하나</li>\n</ul>\n<h3 id=\"-521-람다를-자바-메서드의-파라미터로-전달\" style=\"position:relative;\"><a href=\"#-521-%EB%9E%8C%EB%8B%A4%EB%A5%BC-%EC%9E%90%EB%B0%94-%EB%A9%94%EC%84%9C%EB%93%9C%EC%9D%98-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0%EB%A1%9C-%EC%A0%84%EB%8B%AC\" aria-label=\" 521 람다를 자바 메서드의 파라미터로 전달 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>🔖 5.2.1 람다를 자바 메서드의 파라미터로 전달</h3>\n<deckgo-highlight-code language=\"java\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    void postponeComputation(int delay, Runnable computation) {}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">    postponeComputation(1000) { println(42) }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>컴파일러는 자동으로 Runnable의 인스턴스로 변환해준다.\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\">postponeComputation(1000, object : Runnable) {\n        override fun run() {\n            println(42)\n        }\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>명시적으로 선언하면 호출할 때마다 새 인스턴스가 생기지만 람다를 사용하면 람다에 해당하는 익명 객체가 재사용된다.</li>\n<li>람다를 inline 표시가 돼 있는 코틀린 함수에 전달하면 익명 클래스가 생성되지 않는다.</li>\n</ul>\n<h3 id=\"-522-sam-변환-람다를-함수형-인터페이스로-명시적-변환\" style=\"position:relative;\"><a href=\"#-522-sam-%EB%B3%80%ED%99%98-%EB%9E%8C%EB%8B%A4%EB%A5%BC-%ED%95%A8%EC%88%98%ED%98%95-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4%EB%A1%9C-%EB%AA%85%EC%8B%9C%EC%A0%81-%EB%B3%80%ED%99%98\" aria-label=\" 522 sam 변환 람다를 함수형 인터페이스로 명시적 변환 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>🔖 5.2.2 SAM 변환: 람다를 함수형 인터페이스로 명시적 변환</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun createAllDoneRunnable(): Runnable {\n    return Runnable { println(&quot;All done!&quot;) }\n}\n\nfun main() {\n    createAllDoneRunnable().run()\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>SAM 생성자는 컴파일러가 생성한 함수로 람다를 단일 추상 메서드 인터페이스의 인스턴스로 명시적으로 변환</li>\n<li>SAM 생성자의 이름은 사용하려는 함수형 인터페이스의 이름과 같다.</li>\n<li>SAM 생성자는 하나의 인자만을 받아 함수형 인터페이스를 구현하는 클래스의 인스턴스를 반환</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">val listener = OnClickListener {view -&gt; // 람다를 사용해 SAM 생성자 호출\n    val text = when (view.id) {\n        button1.id -&gt; &quot;First button&quot;\n        button2.id -&gt; &quot;Second button&quot;\n        else -&gt; &quot;Unknown button&quot;\n    }\n    toast(text)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>값을 반환할 때 외에 람다로 생성한 함수형 인터페이스 인스턴스를 변수에 저장해야 하는 경우에도 SAM 생성자 사용</li>\n<li>람다에는 익명 객체와 달리 인스턴스 자신을 가리키는 <code>this</code>가 없다.\n<ul>\n<li>람다 안에서 <code>this</code>는 그 람다를 둘러싼 클래스의 인스턴스를 가리킨다.</li>\n</ul>\n</li>\n<li>SAM 변환을 컴파일로가 자동으로 수행할 수 있지만 가끔 오버로드한 메서드 중에서 어떤 타입의 메서드를 선택해 람다를 변환해 넘겨줘야 할지 모호한 때에는 명시적으로 SAM 생성자 적용하면 된다.</li>\n</ul>\n<h2 id=\"-53-코틀린에서-sam-인터페이스-정의-fun-interface\" style=\"position:relative;\"><a href=\"#-53-%EC%BD%94%ED%8B%80%EB%A6%B0%EC%97%90%EC%84%9C-sam-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EC%A0%95%EC%9D%98-fun-interface\" aria-label=\" 53 코틀린에서 sam 인터페이스 정의 fun interface 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>📖 5.3 코틀린에서 SAM 인터페이스 정의: fun interface</h2>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun interface IntCondition {\n    fun check(i: Int): Boolean\n    fun checkString(s: String) = check(s.toInt())\n    fun checkChar(c: Char) = check(c.digitToInt())\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>fun interface</code>라고 정의된 타입의 파라미터를 받는 함수가 있을 때 람다 구현이나 람다에 대한 참조를 직접 넘길 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun checkCondition(i: Int, condition: IntCondition): Boolean {\n    return condition.check(i)\n}\n\nfun main() {\n    checkCondition(1) { it % 2 != 0} // 람다 직접 사용\n\n    val isOdd: (Int) -&gt; Boolean = { it % 2 != 0 }\n    checkCondition(1, isOdd) // 시그니처가 일치하는 람다에 대한 참조 사용\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>함수형 타입 시그니처로 표현할 수 없는 연산이나 더 복잡한 계약을 표현하려면 함수형 인터페이스가 좋은 선택</li>\n</ul>\n<h2 id=\"-54-수신-객체-지정-람다-with-apply-also\" style=\"position:relative;\"><a href=\"#-54-%EC%88%98%EC%8B%A0-%EA%B0%9D%EC%B2%B4-%EC%A7%80%EC%A0%95-%EB%9E%8C%EB%8B%A4-with-apply-also\" aria-label=\" 54 수신 객체 지정 람다 with apply also 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>📖 5.4 수신 객체 지정 람다: with, apply, also</h2>\n<ul>\n<li>수신 객체를 명시하지 않고 람다의 본문 안에서 다른 객체의 메서드를 호출할 수 있게 하는 것</li>\n</ul>\n<h3 id=\"-541-with-함수\" style=\"position:relative;\"><a href=\"#-541-with-%ED%95%A8%EC%88%98\" aria-label=\" 541 with 함수 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>🔖 5.4.1 with 함수</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun alphabet(): String {\n    val result = StringBuilder()\n    for (letter in &#39;A&#39;..&#39;Z&#39;) {\n        result.append(letter)\n    }\n    result.append(&quot;\\nNow I know the alphabet!&quot;)\n    return result.toString()\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>매번 result라는 이름을 반복 사용</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun alphabet(): String {\n    val stringBuilder = StringBuilder()\n    return with(stringBuilder) { // 메서드를 호출하려는 수신 객체를 지정\n        for (letter in &#39;A&#39;..&#39;Z&#39;) {\n            this.append(letter)\n        }\n        this.append(&quot;\\nNow I know the alphabet!&quot;)\n        this.toString()\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>위 예시의 파라미터는 두개다.\n<ul>\n<li>stringBuilder와 람다</li>\n</ul>\n</li>\n<li>with 함수는 첫 번째 인자로 받은 객체를 두 번째 인자로 받은 람다의 수신 객체로 만든다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun alphabet(): String {\n    val stringBuilder = StringBuilder()\n    return with(stringBuilder) { // 메서드를 호출하려는 수신 객체를 지정\n        for (letter in &#39;A&#39;..&#39;Z&#39;) {\n            append(letter)\n        }\n        append(&quot;\\nNow I know the alphabet!&quot;)\n        toString()\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>람다 안에서는 명시적인 this 참조를 사용해 그 수신 객체에 접근할 수 있다.\n<ul>\n<li>this를 없애고 메서드나 프로퍼티 이름만 사용해 접근 가능</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun alphabet() = with(StringBuilder()) {\n        for (letter in &#39;A&#39;..&#39;Z&#39;) {\n            append(letter)\n        }\n        append(&quot;\\nNow I know the alphabet!&quot;)\n        toString()\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>식을 바로 반환</li>\n</ul>\n<h3 id=\"-542-apply-함수\" style=\"position:relative;\"><a href=\"#-542-apply-%ED%95%A8%EC%88%98\" aria-label=\" 542 apply 함수 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>🔖 5.4.2 apply 함수</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun alphabet() = StringBuilder().apply {\n        for (letter in &#39;A&#39;..&#39;Z&#39;) {\n            append(letter)\n        }\n        append(&quot;\\nNow I know the alphabet!&quot;)\n}.toString()</code>\n        </deckgo-highlight-code>\n<ul>\n<li>apply는 항상 자신에 전달된 객체(수신 객체)를 반환한다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun createViewWithCustomAttributes(context: Context) =\n    TextView(context).apply {\n        text = &quot;Sample Text&quot;\n        textSize = 20.0\n        setPadding(10, 0, 0, 0)\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>apply를 객체 초기화에 활용할 수 있다.</li>\n<li>java의 builder와 비슷하다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun alphabet() = buildString {\n        for (letter in &#39;A&#39;..&#39;Z&#39;) {\n            append(letter)\n        }\n        append(&quot;\\nNow I know the alphabet!&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li><code>buildString</code> 함수는 <code>StringBuilder</code>를 활용해 <code>String</code>을 만드는 경우 사용할 수 있는 우아한 해법</li>\n<li><code>buildList</code>, <code>buildSet</code>, <code>buildMap</code></li>\n</ul>\n<h3 id=\"-543-객체에-추가-작업-수행-also\" style=\"position:relative;\"><a href=\"#-543-%EA%B0%9D%EC%B2%B4%EC%97%90-%EC%B6%94%EA%B0%80-%EC%9E%91%EC%97%85-%EC%88%98%ED%96%89-also\" aria-label=\" 543 객체에 추가 작업 수행 also 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>🔖 5.4.3 객체에 추가 작업 수행: also</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val fruits = listOf(&quot;Apple&quot;, &quot;Banana&quot;, &quot;Cherry&quot;)\n    val uppercaseFruits = mutableListOf&lt;String&gt;()\n    val reversedLongFruits = fruits\n        .map { it.uppercase() }\n        .also { uppercaseFruits.addAll(it) }\n        .filter { it.length &gt; 5 }\n        .also { println(it) }\n        .reversed()\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>수신 객체에 대해 어떤 동작을 수행한 후 수신 객체 반환</li>\n<li>also의 람다 안에서는 수신 객체를 인자로 참조\n<ul>\n<li>디폴트로 it</li>\n</ul>\n</li>\n<li>원래의 수신 객체를 인자로 받는 동작을 실행할 때 also가 유용하다.</li>\n</ul>","excerpt":"람다는 기본적으로 다른 함수에 넘길 수 있는 작은 코드 조각을 의미 📖 5.1 람다식과 멤버 참조 🔖 5.1.1 람다 소개: 코드 블록을 값으로 다루기 람다를 메서드가 하나뿐인 익명 객체 대신 사용할 수 있다. 🔖 5.1.2 람다와 컬렉션 maxByOrNull 함수를 이용하면 편한다. 람다가 인자를 하나만 받고 그 인자에 구체적인 이름을 붙이고 싶지 않기 때문에 it이라는 암시적 이름을 사용한다. 멤버 참조 또한 사용할 수 있다. 🔖 5.1.…","fields":{"slug":"/backend/kotlin-in-action/5장-람다를_사용한_프로그래밍/"},"frontmatter":{"title":"Kotlin in Action - 5장 람다를 사용한 프로그래밍","thumbnail":{"childImageSharp":{"fluid":{"src":"/static/f7f7ddfa31d1614405dc5af1487b9ec4/9c94d/kotlin-in-action.png"}}},"draft":false,"category":"Back-End","tags":["Kotlin"],"date":"March 30, 2025"}},"node":{"id":"f5d54d4a-020c-5fd7-979c-ce466f4ff198","html":"<h2 id=\"-41-클래스-계층-정의\" style=\"position:relative;\"><a href=\"#-41-%ED%81%B4%EB%9E%98%EC%8A%A4-%EA%B3%84%EC%B8%B5-%EC%A0%95%EC%9D%98\" aria-label=\" 41 클래스 계층 정의 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 4.1 클래스 계층 정의</h2>\n<h3 id=\"-411-코틀린-인터페이스\" style=\"position:relative;\"><a href=\"#-411-%EC%BD%94%ED%8B%80%EB%A6%B0-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4\" aria-label=\" 411 코틀린 인터페이스 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 4.1.1 코틀린 인터페이스</h3>\n<ul>\n<li>코틀린 인터페이스 안에는 추상 메서드뿐 아니라 구현이 있는 메서드도 정의할 수 있다.\n<ul>\n<li>다만, 인터페이스에는 아무런 상태도 들어갈 수 없다.</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface Clickable {\n    fun click()\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Button : Clickable {\n    override fun click() = println(&quot;I was clicked&quot;)\n}\n\nfun main() {\n    Button().click()\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>상속이나 composition에서 모두 클래스 이름 뒤에 콜론을 붙이고 인터페이스나 클래스 이름을 적는 방식을 사용한다.</li>\n<li>클래스는 인터페이스를 원하는 개수 제한 없이 마음대로 구현할 수 있지만 클래스는 오직 하나만 확장할 수 있다.</li>\n<li>오버라이드를 할 때 override 변경자를 꼭 사용해야 한다.\n<ul>\n<li>상위 클래스에 있는 메서드 오버라이딩 방지</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface Clickable {\n    fun click()\n    fun showOff() = println(&quot;I&#39;m clickable!&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>디폴트 구현 가능</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface Focusable {\n    fun setFocus(b: Boolean) = println(&quot;I ${if (b) &quot;got&quot; else &quot;lost&quot;} focus.&quot;)\n    \n    fun showOff() = println(&quot;I&#39;m focusable!&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>한 클래스에서 두 인터페이스를 함께 구현한 후, 동일한 showOff 디폴트 구현을 선택하려면 컴파일러 에러가 발생함.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Button : Clickable, Focusable {\n    override fun click() = println(&quot;I was clicked&quot;)\n    \n    override fun showOff() {\n        super&lt;Clickable&gt;.showOff()\n        super&lt;Focusable&gt;.showOff()\n    }\n}</code>\n        </deckgo-highlight-code>\n<h3 id=\"-412-open-final-abstract-변경자-기본적으로-final\" style=\"position:relative;\"><a href=\"#-412-open-final-abstract-%EB%B3%80%EA%B2%BD%EC%9E%90-%EA%B8%B0%EB%B3%B8%EC%A0%81%EC%9C%BC%EB%A1%9C-final\" aria-label=\" 412 open final abstract 변경자 기본적으로 final permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 4.1.2 open, final, abstract 변경자: 기본적으로 final</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">open class RichButton : Clickable {\n    fun disable() {}\n    open fun animate() {}\n    override fun click() {}\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>기본적으로 모든 클래스와 메서드는 final이다.\n<ul>\n<li>클래스에 대해 하위 클래스를 만들 수 없고, 기반 클래스의 메서드를 하위 클래스가 오버라이드할 수도 없다.</li>\n</ul>\n</li>\n<li>어떤 클래스의 상속을 허용하려면 open 변경자를 붙여야 한다.\n<ul>\n<li>메서드나 프로퍼티 또한 마찬가지</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">open class RichButton : Clickable {\n    final override fun click() {}\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>명시적으로 오버라이드 금지하려면 final 표시</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">abstract class Animated { // 추상클래스의 인스턴스 만들 수 없음.\n    abstract val animationSpeed: Double // 추상 프로퍼티: 하위 클래스는 반드시 값이나 접근자 제공\n    val keyframes: Int = 20\n    open val frames: Int = 60\n    \n    abstract fun animate() // 추상함수: 하위 클래스는 반드시 오버라이드해야함.\n    open fun stopAnimating() {}\n    fun animateTwice() {}\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>추상클래스는 인스턴스화할 수 없다.</li>\n</ul>\n<h3 id=\"-413-가시성-변경자-기본적으로-공개\" style=\"position:relative;\"><a href=\"#-413-%EA%B0%80%EC%8B%9C%EC%84%B1-%EB%B3%80%EA%B2%BD%EC%9E%90-%EA%B8%B0%EB%B3%B8%EC%A0%81%EC%9C%BC%EB%A1%9C-%EA%B3%B5%EA%B0%9C\" aria-label=\" 413 가시성 변경자 기본적으로 공개 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 4.1.3 가시성 변경자: 기본적으로 공개</h3>\n<ul>\n<li>가시성 변경자는 코드 기반에 있는 선언에 대한 클래스 외부 접근을 제어</li>\n<li>public, protected, private</li>\n<li>기본적으로 public</li>\n<li>module 안으로만 한정된 가시성을 위해 internal 제공\n<ul>\n<li>module: 함께 컴파일되는 코틀린 파일의 집합</li>\n</ul>\n</li>\n<li>패키지 전용 가시성 개념이 없음</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">internal open class TalkativeButton {\n    private fun yell() = println(&quot;Hey!&quot;)\n    protected fun whisper() = println(&quot;Let&#39;s talk!&quot;)\n}\n\nfun TalkativeButton.giveSpeech() { // 오류\n    yell() // 오류\n    \n    whisper() // 오류\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>기반 타입 목록에 들어있는 타입이나 제네릭 클래스의 타입 파라미터에 들어있는 타입의 가시성은 그 클래스 자신의 가시성과 같거나 더 높아야 하고, 메서드의 시그니처에 사용된 모든 타입의 가시성은 그 메서드의 가시성과 같거나 더 높아야 함.</li>\n<li>클래스를 확장한 함수는 그 클래스의 private이나 protected 멤버에 접근할 수 없다.</li>\n</ul>\n<h3 id=\"-414-내부-클래스와-내포된-클래스-기본적으로-내포-클래스\" style=\"position:relative;\"><a href=\"#-414-%EB%82%B4%EB%B6%80-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%EB%82%B4%ED%8F%AC%EB%90%9C-%ED%81%B4%EB%9E%98%EC%8A%A4-%EA%B8%B0%EB%B3%B8%EC%A0%81%EC%9C%BC%EB%A1%9C-%EB%82%B4%ED%8F%AC-%ED%81%B4%EB%9E%98%EC%8A%A4\" aria-label=\" 414 내부 클래스와 내포된 클래스 기본적으로 내포 클래스 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 4.1.4 내부 클래스와 내포된 클래스: 기본적으로 내포 클래스</h3>\n<ul>\n<li>자바와 달리 내포 클래스는 명시적으로 요청하지 않는 한 바깥쪽 클래스 인스턴스에 대한 접근 권한이 없다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface State : Serializable\n\ninterface View {\n    fun getCurrentState(): State\n    fun restoreState(state: State) {}\n}\n\nclass Button : View {\n    override fun getCurrentState(): State = ButtonState()\n    override fun restoreState(state: State) {}\n    class ButtonState : State {}\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>내포된 클래스에 아무런 변경자도 없으면 자바 static 내포 클래스와 같다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Outer {\n    inner class Inner {\n        fun getOuterReference(): Outer = this@Outer\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>내부 클래스에서 바깥쪽 클래스의 참조에 접근하려면 this@Outer라고 써야 한다.</li>\n</ul>\n<h3 id=\"-415-봉인된-클래스-확장이-제한된-클래스-계층-정의\" style=\"position:relative;\"><a href=\"#-415-%EB%B4%89%EC%9D%B8%EB%90%9C-%ED%81%B4%EB%9E%98%EC%8A%A4-%ED%99%95%EC%9E%A5%EC%9D%B4-%EC%A0%9C%ED%95%9C%EB%90%9C-%ED%81%B4%EB%9E%98%EC%8A%A4-%EA%B3%84%EC%B8%B5-%EC%A0%95%EC%9D%98\" aria-label=\" 415 봉인된 클래스 확장이 제한된 클래스 계층 정의 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 4.1.5 봉인된 클래스: 확장이 제한된 클래스 계층 정의</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface Expr\nclass Num(val value: Int) : Expr\nclass Sum(val left: Expr, val right: Expr) : Expr\n\nfun eval(e: Expr): Int =\n    when (e) {\n        is Num -&gt; e.value\n        is Sum -&gt; eval(e.left) + eval(e.right)\n        else -&gt; throw IllegalArgumentException(&quot;Unknown expression&quot;)\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>when을 사용할 때 else는 강제이다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">sealed class Expr\nclass Num(val value: Int) : Expr()\nclass Sum(val left: Expr, val right: Expr) : Expr()\n\nfun eval(e: Expr): Int =\n    when (e) {\n        is Num -&gt; e.value\n        is Sum -&gt; eval(e.left) + eval(e.right)\n    }</code>\n        </deckgo-highlight-code>\n<ul>\n<li>sealed 변경자를 붙이면 그 상위 클래스를 상속한 하위 클래스의 가능성을 제한할 수 있다.</li>\n<li>하위 클래스들은 반드시 컴파일 시점에 알려져야 하며, sealed 클래스가 정의된 패키지와 같은 패키지에 속해야 하며, 모든 하위클래스가 같은 모듈 안에 위치해야 한다.</li>\n<li>디폴트 분기(else)가 필요 없다.</li>\n<li>sealed 변경자는 클래스가 추상 클래스임을 명시한다.\n<ul>\n<li>abstract를 붙일 필요가 없음.</li>\n<li>추상 멤버를 선언한 수 있음.</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">sealed interface Toggleable {\n    fun toggle()\n}\n\nclass LightSwitch : Toggleable {\n    override fun toggle() = println(&quot;Lights!&quot;)\n}\n\nclass Camera: Toggleable {\n    override fun toggle() = println(&quot;Camera!&quot;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>봉인된 인터페이스도 똑같은 규칙을 따름.</li>\n<li>봉인된 인터페이스가 속한 모듈이 컴파일되고 나면 이 인터페이스에 대한 새로운 구현을 밖에서 추가할 수 없다.</li>\n</ul>\n<h2 id=\"-42-뻔하지-않은-생성자나-프로퍼티를-갖는-클래스-선언\" style=\"position:relative;\"><a href=\"#-42-%EB%BB%94%ED%95%98%EC%A7%80-%EC%95%8A%EC%9D%80-%EC%83%9D%EC%84%B1%EC%9E%90%EB%82%98-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0%EB%A5%BC-%EA%B0%96%EB%8A%94-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%84%A0%EC%96%B8\" aria-label=\" 42 뻔하지 않은 생성자나 프로퍼티를 갖는 클래스 선언 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 4.2 뻔하지 않은 생성자나 프로퍼티를 갖는 클래스 선언</h2>\n<h3 id=\"-421-클래스-초기화-주-생성자와-초기화-블록\" style=\"position:relative;\"><a href=\"#-421-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%B4%88%EA%B8%B0%ED%99%94-%EC%A3%BC-%EC%83%9D%EC%84%B1%EC%9E%90%EC%99%80-%EC%B4%88%EA%B8%B0%ED%99%94-%EB%B8%94%EB%A1%9D\" aria-label=\" 421 클래스 초기화 주 생성자와 초기화 블록 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 4.2.1 클래스 초기화: 주 생성자와 초기화 블록</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class User(val nickname: String)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>클래스 이름 뒤에 오는 괄호로 둘러쌓인 코드를 <strong>주 생성자</strong>라고 부른다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class User constructor(_nickname: String) {\n    val nickname: String\n    \n    init {\n        nickname = _nickname\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>constructor 키워드는 주 생성자나 부 생성자 정의를 시작할 때 사용한다.</li>\n<li>init 키워드는 초기화 블록을 시작한다.</li>\n<li>주 생성자 앞에 별다른 어노테이션이나 가시성 변경자가 없다면 constructor를 생략해도 된다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class User(val nickname: String, val isSubscribed: Boolean = true)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>생성자 파라미터에도 기본값을 정의할 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">open class User(val nickname: String)\n\nclass SocialUser(nickname: String) : User(nickname)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>기반 클래스의 생성자가 인자를 받아야 한다면 클래스의 주 생성자에서 기반 생성자를 호출해야 할 필요가 있다.</li>\n<li>클래스를 정의할 때 별도로 생성자를 정의하지 않으면 컴파일러가 자동으로 인자가 없는 디폴트 생성자를 만들어준다.\n<ul>\n<li>기반 클래스의 이름 뒤에 빈 괄호 필요</li>\n<li>인터페이스의 경우 생성자가 없으므로 괄호가 없음.</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Secretive private constructor(private val agentName: String) {}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>클래스 외부에서 인스턴스화하지 못하게 막고 싶다면 private 선언</li>\n</ul>\n<h3 id=\"-422-부-생성자-상위-클래스를-다른-방식으로-초기화\" style=\"position:relative;\"><a href=\"#-422-%EB%B6%80-%EC%83%9D%EC%84%B1%EC%9E%90-%EC%83%81%EC%9C%84-%ED%81%B4%EB%9E%98%EC%8A%A4%EB%A5%BC-%EB%8B%A4%EB%A5%B8-%EB%B0%A9%EC%8B%9D%EC%9C%BC%EB%A1%9C-%EC%B4%88%EA%B8%B0%ED%99%94\" aria-label=\" 422 부 생성자 상위 클래스를 다른 방식으로 초기화 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 4.2.2 부 생성자: 상위 클래스를 다른 방식으로 초기화</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">open class Downloader {\n    constructor(url: String?) {}\n    \n    constructor(uri: URI?) {}\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린은 코틀린의 디폴트 파라미터 값과 이름 붙은 인자 문법을 사용하므로 부생성자가 필요할 일이 적다.</li>\n<li>상위 클래스에서 super() 키워드를 통해 자신에 대응하는 상위 클래스 생성자를 호출한다.</li>\n<li>this()를 통해 클래스 자신의 다른 생성자를 호출할 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class MyDownloader : Downloader() {\n    constructor(url: String?) : this(URI(url))\n    constructor(uri: URI?) : super(uri)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>클래스에 주 생성자가 없다면 모든 부 생성자는 반드시 상위 클래스를 초기화하거나 다른 생성자에게 생성을 위임해야 한다.</li>\n<li>부 생성자가 필요한 주된 이유는 자바 상호운영성이다.</li>\n</ul>\n<h3 id=\"-423-인터페이스에-선언된-프로퍼티-구현\" style=\"position:relative;\"><a href=\"#-423-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4%EC%97%90-%EC%84%A0%EC%96%B8%EB%90%9C-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0-%EA%B5%AC%ED%98%84\" aria-label=\" 423 인터페이스에 선언된 프로퍼티 구현 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 4.2.3 인터페이스에 선언된 프로퍼티 구현</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface User {\n    val nickname: String\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>인터페이스에 추상 프로퍼티 선언을 넣을 수 있다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class PrivateUser(override val nickname: String) : User\n\nclass SubscribingUser(val email: String) : User {\n    override val nickname: String\n        get() = email.substringBefore(&#39;@&#39;)\n}\n\nclass SocialUser(val accountId: Int) : User {\n    override val nickname: getFacebookName(accountId)\n}\n\nfun getNameFromSocialNetwork(accountId: Int) = &quot;bottleh$accountId&quot;</code>\n        </deckgo-highlight-code>\n<ul>\n<li>인터페이스의 프로퍼티 구현하기</li>\n<li>인터페이스에 추상 프로퍼티뿐 아니라 게터와 세터가 있는 프로퍼티를 선언할 수도 있다.\n<ul>\n<li>위와 같은 게터와 세터는 뒷받침하는 필드를 참조할 수 없다.</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface EmailUser {\n    val email: String\n    val nickname: String\n        get() = email.substringBefore(&#39;@&#39;)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>하위 클래스는 email을 반드시 오버라이딩</li>\n<li>nickname 상속 가능</li>\n</ul>\n<h4 id=\"️-함수-대신-프로퍼티를-사용할-때\" style=\"position:relative;\"><a href=\"#%EF%B8%8F-%ED%95%A8%EC%88%98-%EB%8C%80%EC%8B%A0-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%A0-%EB%95%8C\" aria-label=\"️ 함수 대신 프로퍼티를 사용할 때 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🛠️ 함수 대신 프로퍼티를 사용할 때</h4>\n<ul>\n<li>예외를 던지지 않는다.</li>\n<li>계산 비용이 적게 든다.</li>\n<li>객체 상태가 바뀌지 않으면 여러 번 호출해도 항상 같은 결과를 돌려준다.</li>\n</ul>\n<h3 id=\"-424-게터와-세터에서-뒷받침하는-필드에-접근\" style=\"position:relative;\"><a href=\"#-424-%EA%B2%8C%ED%84%B0%EC%99%80-%EC%84%B8%ED%84%B0%EC%97%90%EC%84%9C-%EB%92%B7%EB%B0%9B%EC%B9%A8%ED%95%98%EB%8A%94-%ED%95%84%EB%93%9C%EC%97%90-%EC%A0%91%EA%B7%BC\" aria-label=\" 424 게터와 세터에서 뒷받침하는 필드에 접근 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 4.2.4 게터와 세터에서 뒷받침하는 필드에 접근</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class User(val name: String) {\n    var address: String = &quot;unspecified&quot;\n    set(value: String) {\n        println(\n            &quot;&quot;&quot;\n                Address was changed for $name:\n                &quot;$field&quot; -&gt; &quot;$value&quot;.\n            &quot;&quot;&quot;.trimIndent())\n        field = value\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>세터에서 뒷받침하는 필드 접근</li>\n<li>접근자의 본문에서는 field라는 특별한 식별자를 통해 뒷받침하는 필드에 접근할 수 있다.</li>\n<li>var인 경우에는 게터나 세터 모두에 field가 없어야 한다.</li>\n</ul>\n<h3 id=\"-425-접근자의-가시성-변경\" style=\"position:relative;\"><a href=\"#-425-%EC%A0%91%EA%B7%BC%EC%9E%90%EC%9D%98-%EA%B0%80%EC%8B%9C%EC%84%B1-%EB%B3%80%EA%B2%BD\" aria-label=\" 425 접근자의 가시성 변경 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 4.2.5 접근자의 가시성 변경</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class LengthCounter {\n    var counter: Int = 0\n        private set // 클래스 밖에서 이 프로퍼티의 값을 바꿀 수 없다.\n\n    fun addWord(word: String) {\n        counter += word.length\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>클래스 외부에서 이 프로퍼티에 값을 쓰려하면 컴파일 시점 오류가 발생</li>\n</ul>\n<h2 id=\"-43-컴파일러가-생성한-메서드-데이터-클래스와-클래스-위임\" style=\"position:relative;\"><a href=\"#-43-%EC%BB%B4%ED%8C%8C%EC%9D%BC%EB%9F%AC%EA%B0%80-%EC%83%9D%EC%84%B1%ED%95%9C-%EB%A9%94%EC%84%9C%EB%93%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%9C%84%EC%9E%84\" aria-label=\" 43 컴파일러가 생성한 메서드 데이터 클래스와 클래스 위임 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 4.3 컴파일러가 생성한 메서드: 데이터 클래스와 클래스 위임</h2>\n<h3 id=\"-431-모든-클래스가-정의해야-하는-메서드\" style=\"position:relative;\"><a href=\"#-431-%EB%AA%A8%EB%93%A0-%ED%81%B4%EB%9E%98%EC%8A%A4%EA%B0%80-%EC%A0%95%EC%9D%98%ED%95%B4%EC%95%BC-%ED%95%98%EB%8A%94-%EB%A9%94%EC%84%9C%EB%93%9C\" aria-label=\" 431 모든 클래스가 정의해야 하는 메서드 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 4.3.1 모든 클래스가 정의해야 하는 메서드</h3>\n<deckgo-highlight-code language=\"kotilin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Customer(val name: String, val postalCode: Int)</code>\n        </deckgo-highlight-code>\n<h4 id=\"️-문자열-표현-tostring\" style=\"position:relative;\"><a href=\"#%EF%B8%8F-%EB%AC%B8%EC%9E%90%EC%97%B4-%ED%91%9C%ED%98%84-tostring\" aria-label=\"️ 문자열 표현 tostring permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🛠️ 문자열 표현: toString()</h4>\n<ul>\n<li>기본 제공되는 객체의 문자열 표현은 클래스 이름과 객체의 주소를 표현함.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Customer(val name: String, val postalCode: Int) {\n    override fun toString() = &quot;Customer(name=$name, postalCode=$postalCode)&quot;\n}</code>\n        </deckgo-highlight-code>\n<h4 id=\"️-객체의-동등성-equals\" style=\"position:relative;\"><a href=\"#%EF%B8%8F-%EA%B0%9D%EC%B2%B4%EC%9D%98-%EB%8F%99%EB%93%B1%EC%84%B1-equals\" aria-label=\"️ 객체의 동등성 equals permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🛠️ 객체의 동등성: equals()</h4>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Customer(val name: String, val postalCode: Int) {\n    override fun equals(other: Any?): Boolean {\n        if (other == null || other !is Customer) \n            return false\n        return name == other.name &amp;&amp; postalCode == other.postalCode\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>코틀린에서 == 연산자는 참조 동일성을 검사하지 않고 객체의 동등성을 검사한다.</li>\n<li>Any는 Java의 Object에 대응되는 모든 클래스의 최상위 클래스</li>\n</ul>\n<h4 id=\"️-해시-컨테이너-hashcode\" style=\"position:relative;\"><a href=\"#%EF%B8%8F-%ED%95%B4%EC%8B%9C-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-hashcode\" aria-label=\"️ 해시 컨테이너 hashcode permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🛠️ 해시 컨테이너: hashCode()</h4>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Customer(val name: String, val postalCode: Int) {\n    override fun equals(other: Any?): Boolean {\n        if (other == null || other !is Customer)\n            return false\n        return name == other.name &amp;&amp; postalCode == other.postalCode\n    }\n    override fun hashCode(): Int = name.hashCode() * 31 + postalCode\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>JVM 언어에서는 hashCode가 지켜야 하는 equals()가 true를 반환하는 두 객체는 반드시 같은 hasCode()를 반환해야 한다.</li>\n</ul>\n<h3 id=\"-432-데이터-클래스-모든-클래스가-정의해야-하는-메서드를-자동으로-생성\" style=\"position:relative;\"><a href=\"#-432-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%81%B4%EB%9E%98%EC%8A%A4-%EB%AA%A8%EB%93%A0-%ED%81%B4%EB%9E%98%EC%8A%A4%EA%B0%80-%EC%A0%95%EC%9D%98%ED%95%B4%EC%95%BC-%ED%95%98%EB%8A%94-%EB%A9%94%EC%84%9C%EB%93%9C%EB%A5%BC-%EC%9E%90%EB%8F%99%EC%9C%BC%EB%A1%9C-%EC%83%9D%EC%84%B1\" aria-label=\" 432 데이터 클래스 모든 클래스가 정의해야 하는 메서드를 자동으로 생성 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 4.3.2 데이터 클래스: 모든 클래스가 정의해야 하는 메서드를 자동으로 생성</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">data class Customer(val name: String, val postalCode: Int)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>equals, hasCode, toString을 모두 포함한다.</li>\n</ul>\n<h4 id=\"️-데이터-클래스와-불변성-copy-메서드\" style=\"position:relative;\"><a href=\"#%EF%B8%8F-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%EB%B6%88%EB%B3%80%EC%84%B1-copy-%EB%A9%94%EC%84%9C%EB%93%9C\" aria-label=\"️ 데이터 클래스와 불변성 copy 메서드 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🛠️ 데이터 클래스와 불변성: copy() 메서드</h4>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Customer(val name: String, val postalCode: Int) {\n    fun copy(name: String = this.name, postalCode: Int = this.postalCode): Customer = Customer(name, postalCode)\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>불변 객체를 사용하면 프로그램에 대해 훨씬 쉽게 추론할 수 있다.</li>\n<li>데이터 클래스는 copy 메서드를 제공한다.\n<ul>\n<li>객체를 복사하면서 일부 프로퍼티를 바꿀 수 있게 해주는 copy 메서드</li>\n</ul>\n</li>\n</ul>\n<h4 id=\"️-클래스-위임-by-키워드-사용\" style=\"position:relative;\"><a href=\"#%EF%B8%8F-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%9C%84%EC%9E%84-by-%ED%82%A4%EC%9B%8C%EB%93%9C-%EC%82%AC%EC%9A%A9\" aria-label=\"️ 클래스 위임 by 키워드 사용 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🛠️ 클래스 위임: by 키워드 사용</h4>\n<p>Decorator 패턴</p>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class DelegatingCollection&lt;T&gt;: Collection&lt;T&gt; {\n    private val innerList = arrayListOf&lt;T&gt;()\n    \n    override val size: Int get() = innerList.size\n    override fun isEmpty(): Boolean = innerList.isEmpty()\n    override fun contains(element: T): Boolean = innerList.contains(element)\n    override fun containsAll(elements: Collection&lt;T&gt;): Boolean = innerList.containsAll(elements)\n    override fun iterator(): Iterator&lt;T&gt; = innerList.iterator()\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class DelegatingCollection&lt;T&gt;(innerList: Collection&lt;T&gt; = mutableListOf&lt;T&gt;()) : Collection&lt;T&gt; by innerList</code>\n        </deckgo-highlight-code>\n<ul>\n<li>상속을 허용하지 않는 클래스에게 새로운 동작을 추가해야 할 때 쓰는 방법</li>\n<li>기존 클래스 대신 사용할 수 있는 데코레이터(새로운 클래스)를 만들되, 기존 클래스와 같은 인터페이스를 데코레이터가 제공하고 기존 클래스를 데코레이터 내부 필드로 유지하는 것</li>\n<li>새로 정의해야 하는 기능은 데코레이터의 메서드로 새로 정의</li>\n<li>기존 기능이 그대로 필요한 부분은 데코레이터의 메서드가 기존 클래스의 메서드에게 요청을 전달</li>\n<li>단점: 준비 코드가 상당히 많이 필요함.</li>\n<li>코틀린은 by 키워드를 통해 제공함.</li>\n</ul>\n<h2 id=\"-44-object-키워드-클래스-선언과-인스턴스-생성을-한꺼번에-하기\" style=\"position:relative;\"><a href=\"#-44-object-%ED%82%A4%EC%9B%8C%EB%93%9C-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%84%A0%EC%96%B8%EA%B3%BC-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%EC%83%9D%EC%84%B1%EC%9D%84-%ED%95%9C%EA%BA%BC%EB%B2%88%EC%97%90-%ED%95%98%EA%B8%B0\" aria-label=\" 44 object 키워드 클래스 선언과 인스턴스 생성을 한꺼번에 하기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 4.4 object 키워드: 클래스 선언과 인스턴스 생성을 한꺼번에 하기</h2>\n<p>object 키워드를 쓰는 상황</p>\n<ul>\n<li>객체 선언</li>\n<li>동반 객체</li>\n<li>객체 식\n<ul>\n<li>자바의 익명 내부 클래스</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"-441-객체-선언-싱글턴을-쉽게-만들기\" style=\"position:relative;\"><a href=\"#-441-%EA%B0%9D%EC%B2%B4-%EC%84%A0%EC%96%B8-%EC%8B%B1%EA%B8%80%ED%84%B4%EC%9D%84-%EC%89%BD%EA%B2%8C-%EB%A7%8C%EB%93%A4%EA%B8%B0\" aria-label=\" 441 객체 선언 싱글턴을 쉽게 만들기 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 4.4.1 객체 선언: 싱글턴을 쉽게 만들기</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">object Payroll {\n    val allEmployees = arrayListOf&lt;Person&gt;()\n    \n    fun calculateSalary() {\n        for (person in allEmployees) {\n            \n        }\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>객체 선언은 object 키워드로 시작</li>\n<li>객체 선언은 클래스를 정의하고 그 클래스의 인스턴스를 만들어 변수에 저장하는 모든 작업을 한 문장으로 처리</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">object CaseInsensitiveFileComparator : Comparator&lt;File&gt; {\n    override fun compare(file1: File, file2: File): Int {\n        return file1.path.compareTo(file2.path, ignoreCase = true)\n    }\n}\n\nfun main() {\n    println(\n        CaseInsensitiveFileComparator.compare(\n            File(&quot;/User&quot;), File(&quot;/user&quot;)\n        )\n    )\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>일반 객체(클래스 인스턴스)를 사용할 수 있는 곳에서는 항상 싱글턴 객체를 사용할 수 있다.</li>\n</ul>\n<h3 id=\"-442-동반-객체-팩토리-메서드와-정적-멤버가-들어갈-장소\" style=\"position:relative;\"><a href=\"#-442-%EB%8F%99%EB%B0%98-%EA%B0%9D%EC%B2%B4-%ED%8C%A9%ED%86%A0%EB%A6%AC-%EB%A9%94%EC%84%9C%EB%93%9C%EC%99%80-%EC%A0%95%EC%A0%81-%EB%A9%A4%EB%B2%84%EA%B0%80-%EB%93%A4%EC%96%B4%EA%B0%88-%EC%9E%A5%EC%86%8C\" aria-label=\" 442 동반 객체 팩토리 메서드와 정적 멤버가 들어갈 장소 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 4.4.2 동반 객체: 팩토리 메서드와 정적 멤버가 들어갈 장소</h3>\n<ul>\n<li>코틀린 클래스 안에는 정적인 멤버가 없다.\n<ul>\n<li>패키지 수준의 최상위 함수와 객체 선언을 활용</li>\n<li>대부분 최상위 함수를 활용하는 편을 더 권장한다.</li>\n</ul>\n</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class MyClass {\n    companion object {\n        fun callMe() {\n            println(&quot;Companion object called&quot;)\n        }\n    }\n}\n\nfun main() {\n    MyClass.callMe()\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>클래스 안에 정의된 객체 중 하나에 companion이라는 특별한 표시를 붙일 수 있다.</li>\n<li>객체 멤버에 접근할 때 자신을 감싸는 클래스의 이름을 통해 직접 사용할 수 있게 된다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    val myObject = MyClass()\n    myObject.callMe() // error\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>해당 클래스의 인스턴스는 동반 객체의 멤버에 접근할 수 없다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class User {\n    val nickname: String\n    \n    constructor(email: String) {\n        nickname = email.substringBefore(&#39;@&#39;)\n    }\n    \n    constructor(socialAccountId: Int) {\n        nickname = getSocialNetworkName(socialAccountId)\n    }\n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class User private constructor(val nickname: String) {\n    companion object {\n        fun newSubscribingUser(email: String) = User(email.substringBefore(&#39;@&#39;))\n        fun newSocialUser(accountId: Int) = User(getNameFromSocialNetwork(accountId))\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>동반 객체가 private 생성자를 호출하기 좋은 위치다.</li>\n<li>바깥쪽 클래스의 private 생성자도 호출할 수 있다.</li>\n<li>즉, 팩토리 패턴을 구현하기 가장 적합한 위치가 될 수 있다.</li>\n<li>팩토리 메서드는 그 팩토리 메서드가 선언된 클래스의 하위 클래스 객체를 반환할 수도 있다.</li>\n</ul>\n<h3 id=\"-443-동반-객체를-일반-객체처럼-사용\" style=\"position:relative;\"><a href=\"#-443-%EB%8F%99%EB%B0%98-%EA%B0%9D%EC%B2%B4%EB%A5%BC-%EC%9D%BC%EB%B0%98-%EA%B0%9D%EC%B2%B4%EC%B2%98%EB%9F%BC-%EC%82%AC%EC%9A%A9\" aria-label=\" 443 동반 객체를 일반 객체처럼 사용 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 4.4.3 동반 객체를 일반 객체처럼 사용</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Person(val name: String) {\n    companion object Loader {\n        fun fromJSON(jsonText: String): Person = /* */\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>필요하다면 동반객체에 이름을 붙일 수 있다.</li>\n</ul>\n<h4 id=\"️-동반-객체에서-인터페이스-구현\" style=\"position:relative;\"><a href=\"#%EF%B8%8F-%EB%8F%99%EB%B0%98-%EA%B0%9D%EC%B2%B4%EC%97%90%EC%84%9C-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EA%B5%AC%ED%98%84\" aria-label=\"️ 동반 객체에서 인터페이스 구현 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🛠️ 동반 객체에서 인터페이스 구현</h4>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface JSONFactory&lt;T&gt; {\n    fun fromJSON(jsonText: String): T\n}\n\nclass Person(val name: String) {\n    companion object : JSONFactory&lt;Person&gt; {\n        override fun fromJSON(jsonText: String): Person = /* */\n    }\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>동반 객체도 인터페이스를 구현할 수 있다.</li>\n</ul>\n<h4 id=\"️-동반-객체-확장\" style=\"position:relative;\"><a href=\"#%EF%B8%8F-%EB%8F%99%EB%B0%98-%EA%B0%9D%EC%B2%B4-%ED%99%95%EC%9E%A5\" aria-label=\"️ 동반 객체 확장 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🛠️ 동반 객체 확장</h4>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class Person(val firstName: String, val lastName: String) {\n    companion object {\n    }\n}\n\nfun Person.Companion.fromJSON(json: String): Person {\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>마치 동반 객체 안에서 <code>fromJSON</code> 함수를 정의한 것처럼 호출할 수 있다.</li>\n<li>동반 객체에 대한 확장 함수를 작성할 수 있으려면 원래 클래스에 동반 객체를 꼭 선언해야 한다.</li>\n</ul>\n<h3 id=\"-444-객체-식-익명-내부-클래스를-다른-방식으로-작성\" style=\"position:relative;\"><a href=\"#-444-%EA%B0%9D%EC%B2%B4-%EC%8B%9D-%EC%9D%B5%EB%AA%85-%EB%82%B4%EB%B6%80-%ED%81%B4%EB%9E%98%EC%8A%A4%EB%A5%BC-%EB%8B%A4%EB%A5%B8-%EB%B0%A9%EC%8B%9D%EC%9C%BC%EB%A1%9C-%EC%9E%91%EC%84%B1\" aria-label=\" 444 객체 식 익명 내부 클래스를 다른 방식으로 작성 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>🔖 4.4.4 객체 식: 익명 내부 클래스를 다른 방식으로 작성</h3>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">interface MouseListener {\n    fun onEnter()\n    fun onClick()\n}\n\nclass Button(private val listener: MouseListener) {\n    \n}</code>\n        </deckgo-highlight-code>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun main() {\n    Button(object : MouseListener {\n        override fun onEnter() {}\n        override fun onClick() {}\n    })\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>객체 식을 사용해 익명 객체를 만든다.</li>\n<li>객체 선언과 같지만 이름이 빠졌다.</li>\n<li>객체 식은 익명 객체 안에서 여러 메서드를 오버라이드해야 하는 경우에 훨씬 더 유용하다.</li>\n</ul>\n<h2 id=\"-45-부가-비용-없이-타입-안전성-추가-인라인-클래스\" style=\"position:relative;\"><a href=\"#-45-%EB%B6%80%EA%B0%80-%EB%B9%84%EC%9A%A9-%EC%97%86%EC%9D%B4-%ED%83%80%EC%9E%85-%EC%95%88%EC%A0%84%EC%84%B1-%EC%B6%94%EA%B0%80-%EC%9D%B8%EB%9D%BC%EC%9D%B8-%ED%81%B4%EB%9E%98%EC%8A%A4\" aria-label=\" 45 부가 비용 없이 타입 안전성 추가 인라인 클래스 permalink\" class=\"post-anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>📖 4.5 부가 비용 없이 타입 안전성 추가: 인라인 클래스</h2>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">fun addExpense(expense: Int) {\n    // 비용을 미국 달러의 센트 단위로 저장\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>200엔 지출을 추가하려면 Int 타입으로만 받기 때문에 다른 의미의 값을 전달하는 것을 막을 수 없다.</li>\n<li>전형적인 해법은 Int 대신 Class를 사용하는 것</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">class UsdCent(val amount: Int)\n\nfun addExpense(expense: UsdCent) {\n    // 비용을 미국 달러의 센트 단위로 저장\n}</code>\n        </deckgo-highlight-code>\n<ul>\n<li>위와 같이 구현하면 GC 비용이 증가하게 된다.</li>\n</ul>\n<deckgo-highlight-code language=\"kotlin\" terminal=\"carbon\" theme=\"one-dark\"  >\n          <code slot=\"code\">@JvmInline\nvalue class UsdCent(val amount: Int)</code>\n        </deckgo-highlight-code>\n<ul>\n<li>인라인 클래스를 사용하면 성능을 희생하지 않고 타입 안정성을 얻을 수 있다.</li>\n<li>실행 시점에 UsdCent의 인스턴스는 감싸진 프로퍼티로 대체된다.</li>\n<li>인라인으로 표시하려면 클래스가 프로퍼티를 하나만 가져야 하며, 그 프로퍼티는 주 생성자에서 초기화돼야 한다.</li>\n<li>인라인 클래스는 클래스 계층에 참여하지 않는다.\n<ul>\n<li>다른 클래스를 상속할 수도, 다른 클래스가 상속할 수도 없음.</li>\n<li>인터페이스 상속, 메서드 정의, 계산된 프로퍼티를 제공</li>\n</ul>\n</li>\n</ul>","excerpt":"📖 4.1 클래스 계층 정의 🔖 4.1.1 코틀린 인터페이스 코틀린 인터페이스 안에는 추상 메서드뿐 아니라 구현이 있는 메서드도 정의할 수 있다. 다만, 인터페이스에는 아무런 상태도 들어갈 수 없다. 상속이나 composition에서 모두 클래스 이름 뒤에 콜론을 붙이고 인터페이스나 클래스 이름을 적는 방식을 사용한다. 클래스는 인터페이스를 원하는 개수 제한 없이 마음대로 구현할 수 있지만 클래스는 오직 하나만 확장할 수 있다. 오버라이드를 할 때 override…","fields":{"slug":"/backend/kotlin-in-action/4장-클래스_객체_인터페이스/"},"frontmatter":{"title":"Kotlin in Action - 4장 클래스, 객체, 인터페이스","thumbnail":{"childImageSharp":{"fluid":{"src":"/static/f7f7ddfa31d1614405dc5af1487b9ec4/9c94d/kotlin-in-action.png"}}},"draft":false,"category":"Back-End","tags":["Kotlin"],"date":"March 23, 2025"}}}},"staticQueryHashes":["2374173507","2996537568","3691437124"]}