<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>dev-siwan</title>
        <link>https://velog.io/</link>
        <description>station3 다방 안드로이드 개발자</description>
        <lastBuildDate>Wed, 22 Dec 2021 06:28:57 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. dev-siwan. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dev_ksw" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Kotlin Coroutine]]></title>
            <link>https://velog.io/@dev_ksw/Kotlin-Coroutine</link>
            <guid>https://velog.io/@dev_ksw/Kotlin-Coroutine</guid>
            <pubDate>Wed, 22 Dec 2021 06:28:57 GMT</pubDate>
            <description><![CDATA[<h2 id="coroutine이란">Coroutine이란</h2>
<p>coroutine은 kotlin 언어를 쓰는 개발자들이 겪는 <strong>스레딩 문제를 직관적인 방식으로 해결 할 수 있는 기술</strong> 이다. </p>
<h2 id="corotuine은-lightweight-thread-이다">Corotuine은 LightWeight Thread 이다.</h2>
<p>기존 자바의 async task 또는 rxjava 등 비동기 작업을 하기 위해서는 하나의 쓰레드를 생성해야 하는데,Coroutine은 <strong>쓰레드 스케쥴링 가능한 코드 블록 또는 코드블록들의 집합내에서 스위칭이 이뤄지기 때문에 OS단의 context switching이 일어나는게 아닌 Coroutine Object 객체들만이 스위칭함으로써 부하가 덜 생긴다.</strong></p>
<h3 id="thread">Thread</h3>
<p><img src="https://images.velog.io/images/dev_ksw/post/250ff12a-1d9e-46fa-8c84-e7c5d3e7c7c3/image.png" alt=""></p>
<blockquote>
<ul>
<li>Task 단위 = <strong>Thread</strong>
다수의 작업 각각에 Thread를 할당 한다.</li>
</ul>
</blockquote>
<ul>
<li><strong>Context Switching</strong>
OS커널에 의한 Context Switching을 통해 동시성을 보장한다.
Blocking: 작업 1(Thread) 이 작업 2(Thread) 의 결과가 나오기까지 기다려야한다면
작업 1 Thread 는 Blocking 되어 그 시간동안 해당 자원을 사용하지 못한다.</li>
</ul>
<h3 id="coroutine">Coroutine</h3>
<p><img src="https://images.velog.io/images/dev_ksw/post/57274830-23c7-4207-bb0f-50b932423705/image.png" alt=""></p>
<blockquote>
<ul>
<li>Task 단위 = <strong>Obejct(Coroutine)</strong>
다수의 작업 각각에 <strong>Object를 할당</strong> 한다.
이 Coroutine Object는 객체를 담는 <strong>JVM Heap에 적재</strong> 된다.</li>
</ul>
</blockquote>
<ul>
<li><strong>Progreammer Switching = No Context Switching</strong>
<strong>프로그래머의 코딩</strong>을 통해 <strong>Switching 시점을 마음대로 정함</strong>으로써 동시성을 보장한다.
<strong>Suspend(Non_Blocking) :</strong> 작업 1(Object) 이 작업 2(Object) 의 결과가 나오기까지 기다려야한다면 작업 1 Object 는 Suspend 되지만 작업 1 을 수행하던 Thread 는 그대로 유효하기 때문에 작업 2 도 작업 1 과 동일한 Thread 에서 실행될 수 있습니다.</li>
</ul>
<h2 id="coroutine-context란"><strong>Coroutine Context란</strong></h2>
<p>Kotlin 표준 라이브러리에 정의된 <strong>CoroutineContext 타입의 값으로 정의된 어떤 context에서 실행</strong>된다.</p>
<h2 id="coroutinescope"><strong>CoroutineScope</strong></h2>
<p>코루틴의 범위, 코루틴 블록을 묶음으로 제어할수 있는 단위</p>
<p>GlobalScope 는 CoroutineScope 의 한 종류입니다. 미리 정의된 방식으로 프로그램 전반에 걸쳐 백그라운드 에서 동작 한다.</p>
<h2 id="dispachers"><strong>Dispachers</strong></h2>
<p>코루틴의 실행을 특정 스레드로 제한하거나, 스레드 풀에 보내거나, 제한을 받지 않는 상태로 실행할 수 있다.</p>
<pre><code>Dispatchers.Default : CPU 사용량이 많은 작업에 사용합니다. 주 스레드에서 작업하기에는 너무 긴 작업 들에게 알맞습니다.
Dispatchers.IO : 네트워크, 디스크 사용 할때 사용합니다. 파일 읽고, 쓰고, 소켓을 읽고, 쓰고 작업을 멈추는것에 최적화되어 있습니다.
Dispatchers.Main : 안드로이드의 경우 UI 스레드를 사용합니다.</code></pre><h2 id="코루틴-쓰는-방법은"><strong>코루틴 쓰는 방법은?</strong></h2>
<pre><code>1. 사용할 Dispatcher 를 결정하고
2. Dispatcher 를 이용해서 CoroutineScope 만들고
3. CoroutineScope 의 launch 또는 async 에 수행할 코드 블록을 넘기면 됩니다.</code></pre><p>ex )_다음 예시에서 <strong>내부 코루틴 블록은 멈추지 않습니다.</strong></p>
<pre><code class="language-kotlin">val scope= CoroutineScope(Dispachers.Main)

val job = scope.launch {

//새로운 Scope 생성
CoroutineScope.launch(Dispachers.Main){

// 외부 코루틴이 취소 되어도 끝까지 돌림

  }

}

job.cancel()</code></pre>
<p>외부 코루틴 블록 과 내부 코루틴 블록은 서로 제어범위가 달라진다.</p>
<p>Job 객체의 cancel() 메서드는 자신이 해당하는 CoroutineScope 의 코루틴 블록을 취소시켜 멈출수 있지만, 내부 <strong>코루틴 블록은 다른 CoroutineScope 로 분리</strong> 되었기 때문에 멈출수 없다.</p>
<p>코루틴 블록이 멈춰도, 내부 코루틴 블록은 끝까지 수행 됨</p>
<h2 id="코루틴-제어를-위한-주요-키워드"><strong>코루틴 제어를 위한 주요 키워드</strong></h2>
<pre><code class="language-kotlin">-launch, async
-runBlocking
-Job, Deferred</code></pre>
<p><strong>launch는 job 객체를 반환</strong> 한다. </p>
<pre><code class="language-kotlin">val job : Job = launch {
    ...
}</code></pre>
<p>반환받은 <strong>Job 객체로 코루틴 블록을 취소하거나, 다음 작업의 수행전 코루틴 블록이 완료 되기를 기다릴 수 있다</strong>.</p>
<pre><code class="language-kotlin">val job:Job = CoroutineScope(Dispachers.IO).launch {
            var i = 0
            while (i &lt; 10) {
                delay(500)
                i++
            }
        }

        job.join() // 완료 대기
        job.cancel() // 취소</code></pre>
<p><strong>여러개의 코루틴 블록을 완료 대기</strong> 시킬 수 있다. ( joinAll(job,job) )</p>
<pre><code class="language-kotlin">val job1: Job = CoroutineScope(Dispatchers.IO).launch {
            var i = 0
            while (i &lt; 10) {
                delay(500)
                println(&quot;job1 state = ${this.coroutineContext.job} i=$i&quot;)
                i++
            }
        }

val job2: Job = CoroutineScope(Dispatchers.IO).launch {
            var i = 0
            while (i &lt; 10) {
                delay(500)
                println(&quot;job2 state = ${this.coroutineContext.job} i=$i&quot;)
                i++
            }
        }

        runBlocking {
            joinAll(job1, job2)
            job1.cancel()
            job2.cancel()

            println(&quot;${job1.job}&quot;)
            println(&quot;${job2.job}&quot;)

        }</code></pre>
<p>위와 같은 예제로 <strong>job1 코루틴 context 객체를</strong> 받아서 돌릴 수 있다.</p>
<pre><code class="language-kotlin">val job1: Job = CoroutineScope(Dispatchers.IO).launch {
            var i = 0
            while (i &lt; 10) {
                delay(500)
                println(&quot;job1 state = ${this.coroutineContext.job} i=$i&quot;)
                i++
            }
        }

        CoroutineScope().launch(job1) { //
            var i = 0
            while (i &lt; 10) {
                delay(500)
                println(&quot;job2 state = ${this.coroutineContext.job} i=$i&quot;)
                i++
            }
        }

        runBlocking {
            job1.join()

        }</code></pre>
<h2 id="async--deferred"><strong>async() — Deferred</strong></h2>
<p>async() 함수로 시작된 코루틴 블록은 Deferred 객체를 반환한다.</p>
<pre><code>val deferred : Deferred&lt;T&gt; = async{
...
    T // 결과값
}</code></pre><p><strong>Deferred 객체를 이용해 제어가 가능하며 동시에 코루틴 블록에서 계산된 결과값을 반환</strong> 한다.</p>
<pre><code class="language-kotlin">val deferred: Deferred&lt;Int&gt; = CoroutineScope(Dispatchers.IO).async {
            var i = 0
            var sum = 0;
            while (i &lt; 10) {
                sum += i
                i++
            }

            sum //결과값 반환
        }

        runBlocking {
            val msg = deferred.await() //값을 반환
            println(msg) // result 출력 45
        }
    }</code></pre>
<p>async 코루틴 블록을 실행할 경우 각<strong>각의 Deferred 객체에 대해서 await() 함수로 코루틴 블록이 완료 될때까지 다음 코드 수행을 대기</strong> 할 수 있습니다. await() 함수는 코루틴 블록이 완료되면 결과를 반환</p>
<pre><code class="language-kotlin">val deferred1 = CoroutineScope(Dispatchers.IO).async {
            var i = 0
            while (i &lt; 10) {
                delay(500)
                i++
            }

            &quot;result1&quot;
        }

        val deferred2 = CoroutineScope(Dispatchers.IO).async {
            var i = 0
            while (i &lt; 10) {
                delay(1000)
                i++
            }

            &quot;result2&quot;
        }

        runBlocking {
            val result1 = deferred1.await()
            val result2 = deferred2.await()

            println(&quot;$result1 , $result2&quot;) // result1 , result 2 출력
        }</code></pre>
<pre><code class="language-kotlin">awaitAll(deferred1,deferred2) //async를 동시에 돌려 결과를 반환 받는다.
</code></pre>
<p>코루틴을 블록을 지연 시킬 수 있다.</p>
<pre><code class="language-kotlin">**CoroutineStart.LAZY**

example :)
- async(context = Dispatchers.IO, start = CoroutineStart.LAZY)
- launch(context = Dispatchers.IO, start = CoroutineStart.LAZY)</code></pre>
<h2 id="start--await-join의-차이점">start() , (await(), join())의 차이점</h2>
<p>start() 함수는 async 코루틴 블록을 실행 시킬땐 블록의 수행 결과를 반환하지 않습니다. 또한 await(),join 함수와 다르게 코루틴 블록이 완료 되는것을 기다리지 않습니다.</p>
<pre><code class="language-kotlin">start
lazy async 0
lazy async 1
lazy async 2
lazy async 3
lazy async 4
end</code></pre>
<pre><code class="language-kotlin">start
end
lazy async 0
lazy async 1
lazy async 2
lazy async 3
lazy async 4</code></pre>
<h3 id="runblocking">runBlocking()</h3>
<p>runBlocking() 함수는 코드 블록이 작업을 완료 하기를 기다린다.</p>
<pre><code class="language-kotlin">runBlocking {
    ...
}</code></pre>
<p>launch() 함수로 시작된 블록은 join() 함수</p>
<p>async() 함수로 시작된 블록은 await() 함수</p>
<p><strong>runBlocking() 함수로 시작된 블록은 아무런 추가 함수 호출 없이</strong> 해당 블록이 완료</p>
<ul>
<li>주의점 :</li>
</ul>
<ol>
<li>runBlocking 코루틴 블록이 <strong>사용하는 스레드는 현재 runBlocking() 함수가 호출된 스레드</strong>가 된다는 것</li>
<li>안드로이드일 경우 <strong>메인스레드에서 호출 하여 시간이 오래 걸리는 작업을 수행하는 경우 ANR 발생</strong> 위험</li>
</ol>
<h2 id="coroutine-취소">Coroutine 취소</h2>
<h3 id="cancelcancelandjoin">cancel/cancelAndJoin</h3>
<p>job을 취소 할 수 있다.</p>
<p>블록내에서 처리 후 cancel()을 호출 할 수 있다.</p>
<h3 id="cancellation-is-cooperative">Cancellation is cooperative</h3>
<p>cancel을 할 경우 coroutine의 모든 suspending functions은 취소를 지원 된다.</p>
<pre><code class="language-jsx">runBlocking {
            val startTime = System.currentTimeMillis()
            val job = launch(Dispatchers.Default) {
                var nextPrintTime = startTime
                var i = 0
                while (i &lt; 5) {
                    // computation loop, just wastes CPU //
                    yield() //여기에 추가하면 정상적으로 취소된다 
                    // print a message twice a second
                    if (System.currentTimeMillis() &gt;= nextPrintTime) {
                        println(&quot;I&#39;m sleeping ${i++} ...&quot;)
                        nextPrintTime += 500L
                    }
                }
            }
            delay(1300L) // delay a bit
            println(&quot;main: I&#39;m tired of waiting!&quot;)
            job.cancelAndJoin() // cancels the job and waits for its completion
            println(&quot;main: Now I can quit.&quot;)
        }</code></pre>
<p>하지만 위 코드는 블록내의 코루틴이 아닌 코틀린 시스템내에서 작동하는 코드 이므로 while문 안의</p>
<p>취소 여부와 관계 없이 동작 한다.</p>
<p><strong>취소 할 수 있는 방법은 두가지가 있다.</strong></p>
<ul>
<li>yeild() - 주기적으로 취소를 체크하는 suspend function을 invoke 시킨다.</li>
<li>if(isActive) - 명시적으로 조건문을 추가 하여 cancel을 체크 한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[AndroidX 간단 요약]]></title>
            <link>https://velog.io/@dev_ksw/AndroidX-%EA%B0%84%EB%8B%A8-%EC%9A%94%EC%95%BD</link>
            <guid>https://velog.io/@dev_ksw/AndroidX-%EA%B0%84%EB%8B%A8-%EC%9A%94%EC%95%BD</guid>
            <pubDate>Thu, 16 Dec 2021 02:33:26 GMT</pubDate>
            <description><![CDATA[<h3 id="androidx-개요">AndroidX 개요</h3>
<p>Androidx는 Android support library를 대체하는 오픈 소스 프로젝트이다.</p>
<ul>
<li>Jectpack 내에서 라이브러리를 개발, 테스트, 패키지화, 버전 및 릴리즈하기 위해 사용한다.</li>
<li>Support Library와 마찬가지로 AndroidX는 Android OS와 별도 구분되며, Android Release전반에 걸쳐 이전 버전과의 호환성을 제공한다.</li>
<li>AndroidX 기능 패키지 및 새 라이브러리를 제공하여 Android Support Library를 완전히 대체 한다.</li>
<li>AndroidX의 모든 패키지는 androidx 문자열로 시작하는 일관된 네임 스페이스가 있으며, androidx.* 패키지로 매핑 되어 있다.</li>
<li>Support Library와 다르게 별도로 유지 관리 되고 업데이트 된다.</li>
</ul>
<h3 id="androidx-사용">AndroidX 사용</h3>
<ul>
<li>Android Studio 3.2 버전 이상, 빌드 28.0 이상 버전부터 사용 가능</li>
<li>gradle.properties파일에서 <em>android.userAndroidX:true</em> 설정</li>
<li>기존 Support Library를 사용하던 프로젝트에서 Android Studio를 통해서 AndroidX migration 기능을 제공하기 때문에 백업 후 마이그레이션이 가능하다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[kotlin  변경자]]></title>
            <link>https://velog.io/@dev_ksw/kotlin-%EB%B3%80%EA%B2%BD%EC%9E%90</link>
            <guid>https://velog.io/@dev_ksw/kotlin-%EB%B3%80%EA%B2%BD%EC%9E%90</guid>
            <pubDate>Wed, 17 Nov 2021 06:24:50 GMT</pubDate>
            <description><![CDATA[<h3 id="openfinalabstract-변경자">open,final,abstract 변경자</h3>
<p>자바의 클래스와 메소드드는 기본적으로 상속에 대해 열려 있지만 코틀린의 클래스와 메소드는 기본적으로 final이다.
어떤 클래스의 상속을 허용하려면 클래스 앞에 open 변경자를 붙여야 한다. 더불어 오버라이드를 허용하고 싶은 메소드나 프로퍼티의 앞에도 open 변경자를 붙여야 한다.</p>
<blockquote>
<p>클래스 내에 오버라이드를 강제 금지 시키려면 final 변경자를 붙이면 된다. 그럼 상속 받은 클래스는 해당 메소드를 오버라이드 할 수 없다.</p>
</blockquote>
<pre><code>interface ClickAble{
    fun showOff()= println(&quot;i&#39;m click able!&quot;)
    fun click()
    fun showOn()
}


open class BaseButton :ClickAble{ //이 클래스는 열려 있는 클래스다. 다른 클래스가 이 클래스를 상속 할 수 있다.

    fun disable(){} //이 함수는 파이널이다. 하위 클래스가 이 메소드를 오버라이드 할 수 없다.

    open fun animate(){} // 이 함수는 열려 있다. 하위 클래스에서 이 메소드를 오버라이드 해도 된다. 

    override fun click(){} // 이 함수는 열려있는 메소드를 오버라이드 한다.

    final override fun showOn() {} // final 변경자를 이용해 오버라이드를 금지 시킨다.

}

class RichButton:BaseButton(){   //BaseButton 상속

    override fun animate() {  //open animate 함수 오버라이드
        super.animate()
    }
      override fun showOff() { //ClickAble interface 메소드 상속
        super.showOff()
    }
}</code></pre><ul>
<li><strong>abstract 추상 클래스 정의하기</strong></li>
</ul>
<blockquote>
<p>일반 자바와 마찬가지로 abstract는 하위 클래스에서 오버라이드 해야 한다.</p>
</blockquote>
<pre><code>abstract class Animated{   //이 클래스는 추상 클래스이다.
    abstract fun animate()  // 이 함수는 추상 함수이다. 이 함수에는 구현이 없다. 하위 클래스에서는 이 함수를 무조건 오버라이드 해야한다.

    open fun stopAnimating(){}
    fun animateTwice(){}
    //추상클래스내에 속하지만 비추상 함수이므로 무조건 오버라이드 할 필요 없다.
}</code></pre><blockquote>
</blockquote>
<p>final(기본 변경자) : 오버라이드 할수 없음 / 클래스 멤버의 기본 변경자
open : 오버리이드 할수 있음 / 반드시 oepn을 명시해야 오버라이드 할 수 있다
abstract : 무조건 오버라이드 해야 함/ 추상 클래스의 멤버에만 이 변경자를 붙일 수 있다. 추상 멤버에는 구현이 있으면 안된다.
override : 상위 클래스나 상위 인스턴스의 멤버를 오버라이드 하는중 / 오버라이드 하는 멤버는 기본적으로 열려있다. 하위 클래스의 오버라이드를 금지하려면 final을 명시해줘야한다.</p>
<h3 id="가시성-변경자">가시성 변경자</h3>
<p>가시성 변경자는 코드 기반에 있는 선언에 대한 클래스 외부 접근을 제어한다. 코틀린에서는 같은 패키지 내 모듈안에서만 볼 수 있는 internal 가시성을 추가했다.</p>
<blockquote>
<p>public(기본 가시성) : 모든곳에서 볼 수 있다.
internal : 같은 모듈 안에서만 볼 수 있다.
protected : 하위 클래스 안에서만 볼 수 있다. 최상위 선언에는 사용 할 수 없다.
private : 같은 클래스 안에서만 볼 수 있다.</p>
</blockquote>
<pre><code>internal open class TalkativeButton :Focusable{
    private fun yell() = println(&quot;Yell&quot;)
    protected fun whisper() = println(&quot;Let&#39;s talk!&quot;)
}

fun TalkativeButton.giveSpeech(){    //public 멤버가 자신의 intenal 수신 타입인 TalkativeButton 노출함
    yell() //private 가시성인 yell 접근 할수 없음
    whisper() //protected whisper을 접근 할수 없음
}</code></pre><blockquote>
<p>internal<br>클래스를 확장한 함수는 private ,  protected 함수를 불러 올 수 없다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[코틀린 인터페이스]]></title>
            <link>https://velog.io/@dev_ksw/%EC%BD%94%ED%8B%80%EB%A6%B0-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4</link>
            <guid>https://velog.io/@dev_ksw/%EC%BD%94%ED%8B%80%EB%A6%B0-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4</guid>
            <pubDate>Mon, 15 Nov 2021 08:50:48 GMT</pubDate>
            <description><![CDATA[<h3 id="코틀린-인터페이스">코틀린 인터페이스</h3>
<p>코틀린 인터페이스는 자바 8 인터페이스와 비슷하다. 안에는 추상 메소드뿐 아니라 구현이 있는 메소드도 정의 할 수 있다.</p>
<pre><code>interface clickable {
  fun click()
}</code></pre><blockquote>
<p>위 코드는 추상 메소드가 있는 인터페이스를 정의 한다. 이 인터페이스를 구현하는 모든 비추상 클래스에 대한 구현을 제공 해야한다.</p>
</blockquote>
<pre><code>class Button0:ClickAble{
    override fun click() = println(&quot;I was clicked&quot;)
}
val btn = Button0()
btn.click()
&gt;&gt;&gt;I was clicked</code></pre><blockquote>
<p>자바에서는 extends와 implements 키워드를 이용하지만 코틀린에서는 클래스 이름 뒤에 콜론(:)뒤에 상속 받을 클래스 또는 인터페이스를 정의한다.
자바의 @Override 애노테이션과 비슷한 override 변경자는 상위 클래스나 상위 인터페이스에 있는 프로퍼티나 메소드를 오버라이드 한다는 뜻이다.</p>
</blockquote>
<pre><code>---디폴트가 있는 메소드 정의

interface ClickAble{
    fun click()
    fun showOff()= println(&quot;i&#39;m click able&quot;)
}

/** class Button0: **/
val btn = Button0()
btn.showOff()
&gt;&gt;&gt;i&#39;m click able
</code></pre><blockquote>
<p>인터페이스 내에 디폴트가 있는 메소드는 클래스 내에서 오버라이드 할 필요 없이 바로 사용이 가능하다.</p>
</blockquote>
<p>만약 2개를 상속한 인터페이스에 같은 이름의 함수값이 있으면 어떻게 처리해야할까??</p>
<pre><code>interface ClickAble{
    fun showOff()= println(&quot;i&#39;m click able&quot;)
}

interface Focusable{
    fun showOff()=pruntln(&quot;i&#39;m focusable&quot;)
}

class Button0:ClickAble,Focusable{
    override fun showOff() {
        super&lt;ClickAble&gt;.showOff()
        super&lt;Focusable&gt;.showOff()
    }
}

val btn = Button0()
btn.showOff()

&gt;&gt;&gt;i&#39;m click able!
i&#39;m focusable!</code></pre><blockquote>
<p>위 처럼 꺽쇠 기호 안에 인터페이스의 타입을 입력해서 부를 수 가 있다.
하지만 단 하나만 호출하게 된다면 어떻게 해야할지 알아보자</p>
</blockquote>
<pre><code>class Button0:ClickAble,Focusable{
    override fun showOff() = super&lt;ClickAble&gt;.showOff()
}

val btn = Button0()
btn.showOff()

&gt;&gt;&gt;i&#39;m click able!</code></pre><blockquote>
<p><strong>자바에서 코틀린의 메소드가 있는 인터페이스 구현하기</strong>
자바의 인터페이스는 디폴트 메소드를 지원하지 않는다. 따라서 디폴트 메소드가 정적 메소드로 들어있는 클래스를 조합해 구현한다. 따라서 자바에서는 코틀린의 디폴트 메소드 구현에 의존 할 수 없다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[코틀린 함수정의와 호출 요약]]></title>
            <link>https://velog.io/@dev_ksw/%EC%BD%94%ED%8B%80%EB%A6%B0-%ED%95%A8%EC%88%98%EC%A0%95%EC%9D%98%EC%99%80-%ED%98%B8%EC%B6%9C-%EC%9A%94%EC%95%BD</link>
            <guid>https://velog.io/@dev_ksw/%EC%BD%94%ED%8B%80%EB%A6%B0-%ED%95%A8%EC%88%98%EC%A0%95%EC%9D%98%EC%99%80-%ED%98%B8%EC%B6%9C-%EC%9A%94%EC%95%BD</guid>
            <pubDate>Fri, 12 Nov 2021 05:25:00 GMT</pubDate>
            <description><![CDATA[<ul>
<li><p>코틀린은 자체 컬렉션을 생성하지 않지만 자바 클래스를 확장해서 더 풍부한 API를 제공한다.
(ex : collection(Int).max() , list.first() ... 등등)</p>
</li>
<li><p>함수 파라미터의 디폴트 값을 정의하면 오버로딩한 함수를 정의할 필요성이 줄어든다. 그리고 이름 붙인 인자를 이용할때 가독성이 더 좋아진다</p>
<pre><code>fun getUser(val name:String=&quot;&quot;, val age:Int=0, val gender:String=&quot;male&quot;):String{
    /** **/
}

println(getUser(name = kim,age = 32))</code></pre></li>
<li><p>코틀린 파일에서 클래스 멤버가 아닌 최상위 함수와 프로퍼티를 선언 할 수 있다.</p>
</li>
<li><p>확장 함수와 프로퍼티를 사용하면 클래스의 소스코드를 바꿀 필요 없이 확장 할 수 있다. 확장 함수를 사용해도 실행 시점에 부가 비용이 들지 않는다.</p>
</li>
<li><p>중위 호출을 통해 인자가 하나밖에 없는 메소드나 확장 함수를 좀 더 깔끔한 구문으로 짤 수 있다.</p>
</li>
<li><p>로컬 함수를 써서 코드를 더 깔끔하게 유지하면서 중복을 제거 할 수 있다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[로컬함수와 확장]]></title>
            <link>https://velog.io/@dev_ksw/%EB%A1%9C%EC%BB%AC%ED%95%A8%EC%88%98%EC%99%80-%ED%99%95%EC%9E%A5</link>
            <guid>https://velog.io/@dev_ksw/%EB%A1%9C%EC%BB%AC%ED%95%A8%EC%88%98%EC%99%80-%ED%99%95%EC%9E%A5</guid>
            <pubDate>Fri, 12 Nov 2021 02:47:41 GMT</pubDate>
            <description><![CDATA[<p>많은 개발자들이 좋은 코드의 중요한 특징중 하나가 중복이 없는것이라 믿는다.
하지만 자바코드를 이용할때에는 DRY(Don&#39;t Repeat YourSelf) 원칙을 피하기는 쉽지 않다.
코틀린에서 이걸 해결하는 방법은 함수를 함수 내부에 중첩 시킬 수 있다.</p>
<pre><code>--- 유저 필드 검증을 체크하는 로직

class User(val id:Int, val name:String,val address :String)

fun saveUser(user:User){
    if (user.name.isEmpty()){
        throw IllegalArgumentException(
            &quot;Can&#39;t save user ${user.id} : empty Name&quot;
        )
    }
    if (user.address.isEmpty()){
        throw IllegalArgumentException(
            &quot;Can&#39;t save user ${user.address} : empty Address&quot;
        )
    }
}

saveUser(User(1,&quot;&quot;,&quot;&quot;))

&gt;&gt;java.lang.IllegalArgumentException: Can&#39;t save user 1 : empty Name</code></pre><blockquote>
<p>여기서는 코드중복이 그렇게 많지 않지만 추 후에 검증에 관련된 value 값들을 하나하나 넣으면 코드가 길어지게 된다. 다음은 로컬 함수를 이용해 유저 필드를 체크하는 로직을 만들어보자</p>
</blockquote>
<pre><code>--- 함수안에 로컬함수를 이용하여 유저필드를 체크하는 로직
class User(val id:Int, val name:String,val address :String)

fun saveUser(user: User) {
    fun validate(value: String, fieldName: String) {
        if (value.isEmpty()) {
            throw IllegalArgumentException(
                &quot;Can&#39;t save user ${user.id} : $fieldName&quot;
            )
        }
    }
    validate(user.name,&quot;Name&quot;)
    validate(user.address,&quot;Address&quot;)

}

saveUser(User(1,&quot;zzz&quot;,&quot;&quot;))
&gt;&gt;java.lang.IllegalArgumentException: Can&#39;t save user 1 : empty Address</code></pre><blockquote>
<p>위와 같이  함수안에 함수를 구현하여 체크를 하는 요소를 줄어들었다.
여기서 좀 더 검증로직을 하는 함수를 만들고 싶으면 확장 함수를 쓰면 된다.</p>
</blockquote>
<pre><code>--- 확장 함수를 이용한 유저필드를 체크하는 로직

fun User.validateBeforeSave(){
    fun validate(value: String, fieldName: String) {
        if (value.isEmpty()) {
            throw IllegalArgumentException(
                &quot;Can&#39;t save user $id : $fieldName&quot;
            )
        }
    }
    validate(name,&quot;Name&quot;)
    validate(address,&quot;Address&quot;)
}

fun saveUser(user: User) {
    user.validateBeforeSave()
}

saveUser(User(1,&quot;zzz&quot;,&quot;&quot;))
&gt;&gt;java.lang.IllegalArgumentException: Can&#39;t save user 1 : empty Address</code></pre><blockquote>
<p>확장함수를 이용하면 위와 같이 id와  name, address를 객체 멤버 처럼 수신객체(this)를 지정하지 않아도 바로 쓸수가 있다. 
함수안에 중첩으로 함수를 넣는게 가능하지만 나중에 코드가 읽기 어려워져 한단계만 중첩 시키는걸 권장한다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[코틀린 컬렉션 처리]]></title>
            <link>https://velog.io/@dev_ksw/%EC%BD%94%ED%8B%80%EB%A6%B0-%EC%BB%AC%EB%A0%89%EC%85%98-%EC%B2%98%EB%A6%AC</link>
            <guid>https://velog.io/@dev_ksw/%EC%BD%94%ED%8B%80%EB%A6%B0-%EC%BB%AC%EB%A0%89%EC%85%98-%EC%B2%98%EB%A6%AC</guid>
            <pubDate>Thu, 11 Nov 2021 09:58:39 GMT</pubDate>
            <description><![CDATA[<h3 id="컬렉션을-처리할-때-쓸수-있는-코틀린-표준-라이브러리-함수">컬렉션을 처리할 때 쓸수 있는 코틀린 표준 라이브러리 함수</h3>
<ul>
<li>vararg 키워드를 사용하면 호출 시 인자 개수가 달라질 수 있는 함수를 정의할 수 있다.</li>
<li>중위(infix)함수 호출 구문을 사용하면 인자가 하나뿐인 메소드를 간편하게 호출 할 수 있다.</li>
<li>구조 분해 선언을 사용하면 복합적인 값을 분해해서 여러 변수에 나눠 담을 수 있다.</li>
</ul>
<h3 id="자바-컬렌션-api-확장">자바 컬렌션 API 확장</h3>
<pre><code>val strings : List&lt;String&gt; = listOf(&quot;first&quot;,&quot;second&quot;,&quot;fourtheeth&quot;)
strings.last
&gt;&gt;fourtheeth

val numbers:Collection&lt;Int&gt; = setOf(1,14,2)
number.max
&gt;&gt;14</code></pre><p> 위의 코드와 같이 last, max는 확장 함수이다.</p>
<pre><code>fun &lt;T&gt;List&lt;T&gt;.last():T { /* 마지막 원소를 반환함 */ }
fun Collection&lt;Int&gt;.max() :Int { /* 컬렉션의 최댓값을 찾음 */ }</code></pre><p>코틀린 표준 라이브러리는 수많은 확장 함수를 포함한다</p>
<h3 id="가변-인자-함수">가변 인자 함수</h3>
<p>리스트를 생성하는 함수를 호출 할 때 원하는 만큼 많이 원소를 전달 할 수 있다.</p>
<pre><code>val list = listOf(2,3,5,7,11)</code></pre><p>라이브러리에서의 함수 정의</p>
<pre><code>fun listOf&lt;T&gt;(vararg values:T):List&lt;T&gt;{ ... }</code></pre><blockquote>
<ol>
<li>자바의 가변길이는 타입뒤에 ...를 붙이지만 코틀린은 vararg 변경자를 붙인다.</li>
<li>가변 길이 인자는 메소드를 호출 할 때 원하는 개수만큼 값을 인자로 넘기면 자바 컴파일러가 배열에 그 값들을 넣어준다.</li>
<li>자바에서는 배열을 그냥 넘기면 되지만 코틀린에서는 배열을 명시적으로 풀어서 각 원소가 인자로 전달되게 해야한다. 이걸 기술적으로 <strong>스프레드 연산자</strong>가 그런 작업을 한다. 실제로 전달하려는 배열 앞에 *를 붙이기만 하면 된다.</li>
</ol>
</blockquote>
<pre><code>--스프레드 연산자
val a = arrayOf(1, 2, 3)
val list = asList(-1, 0, *a, 4)
println(list)
&gt;&gt;[-1, 0, 1, 2, 3, 4]</code></pre><h3 id="중위-호출과-구조-분해-선언">중위 호출과 구조 분해 선언</h3>
<p>간단하게 mapOf 함수를 이용해보자</p>
<pre><code>val map = mapOf(1 to &quot;one&quot;, 7 to &quot;seven&quot;, 53 to &quot;fifity-three&quot;)</code></pre><p>여기서 to 키워드는 본래 코틀린에 있던 키워드가 아니다. 
이 코드는 <strong>중위호출</strong>(infix call)이라는 특별한 방식으로 to라는 일반 메소드를 호출 한 것이다.
 중위 호출 시에는 수신 객체와 유일한 메소드 인자 사이에 메소드 이름을 넣는다.</p>
<pre><code>infix fun &lt;A, B&gt; A.to(that: B): Pair&lt;A, B&gt; = Pair(this, that)</code></pre><p>이 to 함수는 Pair 인스턴스를 반환한다. Pair는 코틀린 표준 라이브러리 클래스로 두 원소 이뤄진 순서쌍을 표현한다.
Pair의 내용으로 두 변수를 즉시 초기화 할 수 있다.</p>
<pre><code>val (number,name) = 1 to &quot;one&quot;</code></pre><p>이런 기능을 <strong>구조 분해 선언</strong>이라 부른다</p>
<ul>
<li><strong>중위호출(infix), 구조 분해(Destructuring) 선의 또 다른 예</strong> </li>
</ul>
<pre><code>---중위호출 다른 예

infix fun Int.multiply(x: Int): Int { //infix로선언되므로중위함수
return this * x
}

println(10 multiply 3)
&gt;&gt; 30

--- 구조 분해 선언 다른 예

 class Car(private val manufacturer:Any, private val model:Any){
   operator fun component1() = manufacturer
   operator fun component2() = model
 }

 val car = Car(&quot;현대&quot;, &quot;그랜저&quot;)
 val (manufacturer, model) = car
 println(&quot;제조사 : $manufacturer, 모델 : $model&quot;)
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[코틀린 확장 함수, 프로퍼티]]></title>
            <link>https://velog.io/@dev_ksw/%EC%BD%94%ED%8B%80%EB%A6%B0-%ED%99%95%EC%9E%A5-%ED%95%A8%EC%88%98-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0</link>
            <guid>https://velog.io/@dev_ksw/%EC%BD%94%ED%8B%80%EB%A6%B0-%ED%99%95%EC%9E%A5-%ED%95%A8%EC%88%98-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0</guid>
            <pubDate>Wed, 10 Nov 2021 02:27:58 GMT</pubDate>
            <description><![CDATA[<h3 id="확장-함수">확장 함수</h3>
<p>어떤 클래스의 멤버 메소드인 것 처럼 호출 할 수 있지만 클래스 밖에 선언된 함수이다.</p>
<pre><code>문자열의 마지막값을 돌려주는 함수

package strings
fun String.lastChar() : Char = this.get(this.length -1)</code></pre><blockquote>
<p>확장 함수를 만들려면 추가하는 함수 이름 앞에 그 함수가 확장할 클래스의 이름을 붙이면 된다.
클래스 이름을 <strong>수신객체 타입</strong> 이라 부르며 확장함수가 호출되는 대상을 <strong>수신 객체</strong> 라고 부른다.</p>
</blockquote>
<pre><code>fun String(수신객체 타입).lastChar: Char = this(수신객체).get(this(수신객체).length - 1)


println(&quot;Kotlin&quot;.lastChar()) //호출
&gt;&gt;n</code></pre><blockquote>
<p>수신 객체 멤버에 this 없이도 사용이 가능하다.</p>
</blockquote>
<pre><code>fun String.lastChar: Char = get(length - 1) //this 생략</code></pre><blockquote>
<ol>
<li>일반적인 인스턴스 메소드의 내부에서와 마찬가지로 수신 객체의 메소드나 프로퍼티를 바로 사용 할 수 있다.</li>
<li>클래스 내부에서만 사용 할 수 있는 private 멤버나 protected 멤버를 사용 할 수 없다</li>
</ol>
</blockquote>
<h3 id="임포트와-확장-함수">임포트와 확장 함수</h3>
<p>외부 클래스에서 확장 함수 정의를 임포트를 통해 사용이 가능하다.
한 클래스 내에서 함수의 같은 이름이 충돌 하는 경우가 자주 생길 수 있는데, 임포트를 통해 개별 함수를 정할 수가 있다.</p>
<pre><code>import string.lastChar

val c = &quot;Kotlin&quot;.lastChar()

-- *를 사용한 임포트도 잘 작동한다.

import strings.*   

val c = &quot;Kotlin&quot;.lastChar()

--- as키워드를 통한 임포트한 클래스나 함수를 다른 이름으로 부를 수 있다.

import string.lastChar as last

val c = &quot;Kotlin&quot;.last()</code></pre><ul>
<li>자바에서의 호출<blockquote>
<p>확장 함수는 수신객체를 첫 번째 인자로 받는 정적 메소드 이다. 때문에 코틀린의 파일명에 따라 자바의 클래스 이름이 선언되기 때문에 StringUtil.kt 파일에 정의 했다면 다음과 같이 호출 할 수 있다. </p>
</blockquote>
</li>
</ul>
<pre><code>char c = StringUtilKt.lastChar(&quot;JAVA&quot;);</code></pre><h3 id="확장함수는-오버라이드-될-수-없다">확장함수는 오버라이드 될 수 없다.</h3>
<p>코틀린의 오버라이드도 객체지향의 오버라이드와 마찬가지로 코딩을 하면 된다.</p>
<pre><code>---- 일반적인 멤버함수 오버라이드

open class View{

open fun click() = println(&quot;View clicked&quot;)
}

class Button:View(){

   override fun click() = println(&quot;Button clicked&quot;)
}

val view:View = Button()
view.clicked()
&gt;&gt;Button clicked</code></pre><ul>
<li>여기서 확장 함수로 showOff라는 메소드를 만들어 테스트를 해보자</li>
</ul>
<pre><code>fun View.showOff() = println(&quot;Im a View!&quot;)
fun Button.showOff() = println(&quot;Im a Button!&quot;)

val view:View = Button()
view.showOff()
&gt;&gt;Im a View!</code></pre><blockquote>
<p>위 코드에서는 view 변수가 Button 실제 객체 타입을 들고 있지만 이 경우 타입이 View이기 때문에 View의 확장 함수가 호출된다. 이유는 확장함수는 static한 정적 메소드로서 컴파일 시점때 미리 View 타입으로 결정하기 때문이다. </p>
</blockquote>
<h3 id="확장프로퍼티">확장프로퍼티</h3>
<pre><code>---확장 프로퍼티 선언 
val String.lastChar:Char
   get() = get(length -1 )</code></pre><blockquote>
<p>확장 함수의 경우와 마찬가지로 확장 프로퍼티도 일반적인 프로퍼티와 같은데, 뒷받침하는 필드가 없어서 기본 게터 구현을 제공 할 수 없으므로 최소한 게터는 꼭 정의를 해야한다.</p>
</blockquote>
<pre><code>---변경 가능한 확장 프로퍼티 선언

var StringBuilder.lastChar:Char
    get() = get (length -1 )
    set(value:Char){
    this.setCharAt(length -1 , value)
    }


println(&quot;Kotlin&quot;.lastChar)
&gt;&gt; n

val sb = StringBuilder(&quot;Kotlin?&quot;)
sb.lastChar = &#39;!&#39;
println(sb)
&gt;&gt; Kotlin!</code></pre><blockquote>
<p>확장 프로퍼티를 사용하는 방법은 멤버 프로퍼티를 사용하는 방법과 같다.
자바에서는 StringUtilKt(코틀린파일네임명).getLastChar(&quot;JAVA&quot;) 처럼 게터나 세터를 명시적으로 호출 해야한다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[코틀린 최상위 함수, 프로퍼티]]></title>
            <link>https://velog.io/@dev_ksw/%EC%BD%94%ED%8B%80%EB%A6%B0-%EA%B0%84%EB%8B%A8-%EC%BB%AC%EB%A0%89%EC%85%98-%EB%B0%8F-%ED%95%A8%EC%88%98-%ED%98%B8%EC%B6%9C2</link>
            <guid>https://velog.io/@dev_ksw/%EC%BD%94%ED%8B%80%EB%A6%B0-%EA%B0%84%EB%8B%A8-%EC%BB%AC%EB%A0%89%EC%85%98-%EB%B0%8F-%ED%95%A8%EC%88%98-%ED%98%B8%EC%B6%9C2</guid>
            <pubDate>Tue, 09 Nov 2021 01:54:43 GMT</pubDate>
            <description><![CDATA[<h3 id="최상위-함수">최상위 함수</h3>
<ul>
<li>기존 자바에서는 하나의 메소드 또는 프로퍼티를 호출하기 위해서는 클래스안에 포함시켜아한다.
하지만 코틀린에서는 메소드 또는 프로퍼티를 파일안에 클래스 없이 최상위 수준에 위치 하면 된다.</li>
</ul>
<pre><code>---아래 코드 처럼 클래스 없이 파일안에 최상위 함수로 선언 할 수 있다.
package strings
JoinStr.kt


fun joinToString():String{...}</code></pre><blockquote>
<p>JVM이 클래스 안에 들어있는 코드만을 실행 할 수 있기 때문에 <strong>컴파일러는 파일을 컴파일 할 때 클래스를 정의</strong> 해준다.</p>
</blockquote>
<ul>
<li>위 코드를 자바코드로 컴파일 했을 때<pre><code>package strings;
</code></pre></li>
</ul>
<p>public class JoinKt{
  public static String joinToString(...){ ... }
}</p>
<pre><code>&gt;클래스 이름은 코틀린 소스 파일의 이름과 대응한다. 코틀린의 모든 최상위 함수는 클래스의 정적인 메소드가 된다.

- 자바에서 코틀린 정적 함수 호출</code></pre><p>import strings.JoinKt;</p>
<p>JoinKt.joinToString(list,&quot;,&quot;,&quot;&quot;,&quot;&quot;)</p>
<pre><code>&gt; - 파일에 대응하는 클래스의 이름 변경
 코틀린 최상위 함수가 포함되는 클래스의 이름을 바꾸고 싶다면 **@JvmName 어노테이션을 추가** 한다.
 어노테이션의 위치는 파일의 맨 앞. 패키지 이름 선언 이전에 위치한다.

 ### 최상위 프로퍼티
 최상위 함수와 마찬가지로 프로퍼티도 파일의 최상위 수준에 놓을 수 있다.
</code></pre><p>var opCount = 0
 fun performOperation(){
    opCount++
    // ...
 }
fun reportOperationCount(){
   println(&quot;Operation performed $opCount times&quot;)
}</p>
<pre><code>&gt;프로퍼티의 값은 정적 필드에 저장된다.

- 최상위 프로퍼티를 활용해 코드에 상수를 추가 할 수 있다. 
</code></pre><p> val UIX_LINE_SEPARATOR =&quot;\n&quot;</p>
<pre><code>
 기본적으로 최상위 프로퍼티도 다른 모든 프로퍼티 처럼 접근자 메소드를 통해 자바에 노출 된다.
 위와 같은 상수를 자연스럽게 이용하려면 const 변경자를 추가하면 된다.
**단 원시 타입과 String타입의 프로퍼티만 const로 지정 가능 **
</code></pre><p>--kotlin---
const val UIX_LINE_SEPARATOR =&quot;\n&quot;</p>
<p>--java---
public static final String UIX_LINE_SEPARATOR =&quot;\n&quot;</p>
<pre><code></code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[코틀린 간단 컬렉션 및 함수 호출]]></title>
            <link>https://velog.io/@dev_ksw/%EC%BD%94%ED%8B%80%EB%A6%B0-%EA%B0%84%EB%8B%A8-%EC%BB%AC%EB%A0%89%EC%85%98-%EB%B0%8F-%ED%95%A8%EC%88%98-%ED%98%B8%EC%B6%9C</link>
            <guid>https://velog.io/@dev_ksw/%EC%BD%94%ED%8B%80%EB%A6%B0-%EA%B0%84%EB%8B%A8-%EC%BB%AC%EB%A0%89%EC%85%98-%EB%B0%8F-%ED%95%A8%EC%88%98-%ED%98%B8%EC%B6%9C</guid>
            <pubDate>Wed, 03 Nov 2021 07:43:50 GMT</pubDate>
            <description><![CDATA[<h3 id="코틀린-컬렉션-간단하게-훑어보기">코틀린 컬렉션 간단하게 훑어보기</h3>
<ul>
<li><p>코틀린에서는 자바와 같이 여러가지 컬렉션을 만들 수 있다.</p>
<pre><code>val set = hashSetOf(1,7,53) //set 컬렉션
val list = arrayList(1,7,53) //arrayList 컬렉션
val map = hashMapOf(1 to &quot;one&quot;,7 to &quot;seven&quot;, 53 to &quot;fifty-three&quot;) //map 컬렉션</code></pre><blockquote>
<p>코틀린의 collection 함수는 자바의 상호작용을 위해 자바의 컬렉션을 통해 제공된다. 코틀린 자체에서 컬렉션을 제공하지 않는다.</p>
</blockquote>
</li>
<li><p>코틀린은 자바보다 컬렉션에 제공되는 함수가 많다.</p>
<pre><code>val strings = listOf(&quot;first&quot;,&quot;second&quot;,&quot;fourteeth&quot;)
println(strings.last())
&gt;&gt;fourteeth
val numbers = setOf(1,14,2)
println(numbers.max())
&gt;&gt;14</code></pre><blockquote>
<p>추후에 자바에 없는 메소드를 코틀린에서는 어떻게 동작하는지 알아보자.</p>
</blockquote>
</li>
</ul>
<h3 id="함수를-호출하기-쉽게-만들기">함수를 호출하기 쉽게 만들기</h3>
<ul>
<li>간단히 list를 출력하는 함수를 만들어보자</li>
</ul>
<pre><code>val list = listOf(1,2,3)
println(list)     //toString()
&gt;&gt; [1,2,3]</code></pre><blockquote>
<p>여기서 내가 원하는 출력값은 단순히 1,2,3이 나오길 원하는데 출력은 [1,2,3]이 나온다.
그럼 우리가 원하는 list의 형태가 나오게 구현하는 예시를 짜보자</p>
</blockquote>
<pre><code>
-- 원하는 출력 형태 : (1,2,3)

fun &lt;T&gt; joinToString(
    collection:Collection&lt;T&gt;,
    separator:String,
    prefix:String,
    postfix :String
):String{
    val result = StringBuilder(prefix)
    for((index,element) in collection.withIndex()){
        if (index &gt;0) result.append(separator)
        result.append(element)
    }
    result.append(postfix)
    return result.toString()

    val list = listOf(1,2,3)
    println(joinToString(list,&quot;,&quot;,&quot;(&quot;,&quot;)&quot;))

    &gt;&gt;(1,2,3)
}</code></pre><blockquote>
<p>결과값이 잘 나온다. 하지만 가독성에 있어서 아쉬운 부분이 많다. 좀 더 깔끔하게 표현을 해보자.</p>
</blockquote>
<ul>
<li>** 코틀린에서는 인자를 딴 이름을 명시 할 수 있다.**</li>
</ul>
<pre><code>println(joinToString(collection = list ,
separator =&quot;,&quot;  ,
prefix = &quot;(&quot; ,
postfix = &quot;)&quot; )
)</code></pre><blockquote>
<p>다음과 같이 이름을 명시하면 좀 더 가독성이 좋아보인다.
하지만 이름을 명시하면 모든 인자 값에 이름을 명시 해야하는 문제점이 있다.
default parameter(디폴트 파라미터) 통해 좀 더 가독성이 좋게 보일 수 있다.
<strong>warning</strong> : 자바로 작성한 코드를 호출 할때는 이름 붙인 인자를 사용할 수가 없다</p>
</blockquote>
<ul>
<li><strong>디폴트 파라미터 값</strong></li>
</ul>
<p>자바의 일부 클래스에서 오버로딩한 메소드가 너무 많아진다는 문제가 있다.
오버로딩 메소드들은 하위 호환성을 유지하거나 API 사용자에게 편의를 더하는 등의 여러가지 이유로 만들어 진다.
어느 경우든 중복이 되는 경우가 많은데 코틀린에서는 함수 선언에 파라미터의 디폴트 값을 지정할 수 있어 이러한 문제점을 피해 갈 수 있다.</p>
<pre><code>
fun &lt;T&gt; joinToString(
    collection:Collection&lt;T&gt;,
    separator:String=&quot;,&quot;, //디폴트 값 &quot;,&quot;이 지정되었다.
    prefix:String=&quot;&quot;, //디폴트 값 &quot;&quot;이 지정되었다.
    postfix :String=&quot;&quot; //디폴트 값 &quot;&quot;이 지정되었다.
):String{
    // *** //
}

println(joinToString(list)) // separator,prefix,postfix 생략
&gt;&gt; 1,2,3
println(joinToString(list,postfix=&quot;;&quot;,prefix=&quot;#&quot;)) prefix,postfix 지정
&gt;&gt; #1,2,3;
</code></pre><blockquote>
<p>위와 같이 디폴트 값을 정해놓으면 필요한 인자만 값을 넣으면 되는 장점이 있다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[코틀린 기초 요약]]></title>
            <link>https://velog.io/@dev_ksw/%EC%BD%94%ED%8B%80%EB%A6%B0-%EA%B8%B0%EC%B4%88-%EC%9A%94%EC%95%BD</link>
            <guid>https://velog.io/@dev_ksw/%EC%BD%94%ED%8B%80%EB%A6%B0-%EA%B8%B0%EC%B4%88-%EC%9A%94%EC%95%BD</guid>
            <pubDate>Wed, 03 Nov 2021 02:36:24 GMT</pubDate>
            <description><![CDATA[<h3 id="코틀린-기초-요약">코틀린 기초 요약</h3>
<ul>
<li>함수를 정의 할 때 fun 키워드를 이용한다. </li>
<li>val : 읽기전용 변수, var : 변경 가능한 변수에 쓰인다.</li>
<li>문자열 템플릿은 변수이름 앞에 $ 붙이거나, 식을 ${식}처럼 블록으로 둘러싸면 변수나 식의 값을 문자열에 넣을 수 있다.</li>
<li>if는 코틀린에서 식이며, 값을 만들어 낸다.</li>
<li>코를린에서는 when은 자바의 switch케이스와 비슷한데 식으로도 이용이 가능하다.</li>
<li>변수의 타입을 검사하고 나면 변수를 캐스팅 하지 않아도 검사한 타입의 변수처럼 사용 할 수 있다.
이 같은 경우 컴파일러가 자동으로 스마트캐스팅을 해준다.</li>
<li>for,while,do-while 루프는 자바가 제공하는 키워드와 비슷하다.</li>
<li>1..5 같은 식은 범위를 만들어낸다. 범위와 수열은 코틀린에서 같은 문법을 사용하며, for 루프에 대한 같은 추상화를 제공한다. 어떤 값이 범위 안에 들어 있거나 들어있지 않은지 검사하기 위해 in 이나 !in 을 이용한다.</li>
<li>코틀린에서 예외처리는 자바와 비슷하다. 다만 코틀린에서는 함수가 던질 수 있는 예외를 선언하지 않아도 된다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[예외처리]]></title>
            <link>https://velog.io/@dev_ksw/%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%AC</link>
            <guid>https://velog.io/@dev_ksw/%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%AC</guid>
            <pubDate>Wed, 03 Nov 2021 02:15:54 GMT</pubDate>
            <description><![CDATA[<h3 id="코틀린의-예외처리">코틀린의 예외처리</h3>
<ul>
<li>코틀린의 예외처리는 자바의 예외처리와 전혀 다르지 않다.</li>
<li>throw를 식으로 처리가 가능하다.<pre><code>if (percentage !in 0..100){
 throw IllegalArgmentException(
     &quot;A percentage value must be between 0 and 100: $percentage&quot;) 
}
</code></pre></li>
</ul>
<p>val pecentage = 
if(num in 0..100) number
else 
throw IllegalArgmentException(
       &quot;A percentage value must be between 0 and 100: $percentage&quot;) </p>
<pre><code>
### try,catch,finally

자바와 마찬가지로 예외처리를 하려면 try,catch,finally 절을 함께 사용한다.
</code></pre><p>-이 코드는 파일에서 각 줄을 읽어 수로 변환하되 그 줄이 올바른 형태가 아니면 null 을 반환하는 예제이다.</p>
<p>  fun readNumber(reader:BufferedReader):Int?{
        try {
            val line = reader.readLine()
            return Integer.parseInt(line)
        }catch (e:NumberFormatException){
            return null
        }finally {
            reader.close()
        }
    }</p>
<p> val reader = BufferedReader(StringReader(&quot;239&quot;))
 println(readNumber(reader))</p>
<blockquote>
<blockquote>
<blockquote>
<p>239</p>
</blockquote>
</blockquote>
</blockquote>
<pre><code>
- 코틀린에서는 try catch문을 이용해 식으로도 만들 수 있다.
~~~
     fun readNumber(reader:BufferedReader){
        val num = try {
            Integer.parseInt(reader.readLine())
        } catch (e: NumberFormatException) {
            null
        }
        println(num)
    }

  val reader = BufferedReader(StringReader(&quot;not a number&quot;))
  println(readNumber(reader))

 &gt;&gt;&gt;null

~~~
&gt;위 코드는 예외가 만족하면 문자열 숫자를 반환하고 아닐 경우 예외처리가 될 경우 null을 반환한다.
1. 식 안에서는 마지막 문장이 리턴값이 된다.
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[while과 for 루프]]></title>
            <link>https://velog.io/@dev_ksw/while%EA%B3%BC-for-%EB%A3%A8%ED%94%84</link>
            <guid>https://velog.io/@dev_ksw/while%EA%B3%BC-for-%EB%A3%A8%ED%94%84</guid>
            <pubDate>Fri, 29 Oct 2021 07:42:53 GMT</pubDate>
            <description><![CDATA[<h3 id="while-루프">while 루프</h3>
<p>코틀린에서 while과 do-while 루프가 있다.
두 루프의 문법은 자바와 다르지 않다.</p>
<pre><code>while(조건){  //조건이 참이 될때까지 본문을 반복 실행한다.
  /*...*/
}

do{   //맨 처음에 본문을 한 번 실행한 다음. 조건이 참인 동안 본문을 반복 실행

}while(조건)</code></pre><h3 id="수에-대한-이터레이션-범위와-수열">수에 대한 이터레이션: 범위와 수열</h3>
<p>코틀린에는 자바의 for 루프(변수를 초기화 하고 루프를 실행 할때마다 갱신하고 루프 조건이 거짓이 될때 반복을 마치는 형태의 루프)에 해당하는 요소가 없다.
루프를 대신하기 위해 코틀린에서는 범위(range)를 사용한다.</p>
<blockquote>
<p>val oneToTen= 1..10</p>
</blockquote>
<pre><code>when을 사용해 피즈버즈 게임 구현(주석 코드 설명)


fun fizzBuzz(i: Int) = when { //return값 문자열로 반환 생략
        i % 15 == 0 -&gt; &quot;FizzBuzz&quot; //정수값 i 가 15로 나눠지면 FizzBuzz로 반환
        i % 3 == 0 -&gt; &quot;Fizz&quot; // 정수값 i 가 3로 나눠지면 Fizz로 반환
        i % 5 == 0 -&gt; &quot;Buzz&quot; 정수값 i 가 5로 나눠지면 Buzz로 반환
        else -&gt; &quot;$i&quot; //그 외는 자신의 숫자로 반환
}

for (i in 1..100){   //1..100까지의 정수에 대해 이터레이션 한다.
     println(fizzBuzz(i))
}

&gt;&gt;&gt; 1 2 Fizz 4 Buzz Fizz 7 ...
</code></pre><pre><code>증가 값을 갖고 범위 이터레이션 하기(주석 코드 설명)
   for (i in 100 downTo 1 step 2){ //downTo : 100에서 1까지 역방향으로 내려온다. 
                                     step : 2 정수값을 건너뛴다.
     println(fizzBuzz(i))
 }

 &gt;&gt;&gt; Buzz 98 Fizz 94 92 FizzBuzz 88 ...</code></pre><ul>
<li><strong>맵에 대한 이터레이션</strong></li>
</ul>
<pre><code>        val binaryReps = TreeMap&lt;Char,String&gt;() //키에 대해 정렬하기 위해 TreeMap 이용

        for (c in &#39;A&#39;..&#39;F&#39;){ //A 부터 F까지 문자의 범위를 사용해 이터레이션 한다.
            val binary = Integer.toBinaryString(c.code) //아스키 코드를 2진 표현으로 변경
            binaryReps[c] = binary //c를 키로 c의 2진 표현을 맵에 넣는다.
            (자바에서는 binaryReps.put(c,bianry)로 코딩
        }

        for ((letter,binary) in binaryReps){ //맵에 대해 이터레이션 한다. 맵의 키와 값을 두변수에 각각 대입한다.
            println(&quot;$letter = $binary&quot;)
        }

 &gt;&gt;&gt;
A = 1000001
B = 1000010
C = 1000011
D = 1000100
E = 1000101
F = 1000110</code></pre><blockquote>
<p>이터레이션에는 숫자 값이 아닌 문자 타입의 값에도 적용 할 수 있다.</p>
</blockquote>
<h3 id="in으로-컬렉션이나-범위의-원소-검사">in으로 컬렉션이나 범위의 원소 검사</h3>
<pre><code>fun isLetter(c:Char) = c in &#39;a&#39;..&#39;z&#39; || c in &#39;A&#39;..&#39;Z&#39; // &#39;a&#39; &lt;= c &amp;&amp; c &lt;= &#39;z&#39;로 변환
fun isNotDigit(c:Char) = c !in &#39;0&#39;..&#39;9&#39;
println(isLetter(&#39;A&#39;))
println(isNotDigit(&#39;0&#39;))


true
false</code></pre><blockquote>
<ol>
<li>in 연산자를 사용해 어떤 값이 범위에 속하느지 검사 할 수 있다.</li>
<li>!in 연산자를 통해 어떤 값이 범위에 속하지 않는지 검사 할 수 있다.</li>
</ol>
</blockquote>
<pre><code>다른 예제

-when 에서 in 사용하기
fun reconzine(c:Char) = when(c){
  in &#39;0&#39;..&#39;9&#39; -&gt; &quot;It&#39;s a digit&quot;
  in &#39;a&#39;..&#39;z&#39;, in &#39;A&#39;..&#39;Z&#39; -&gt; &quot;It&#39;s a letter&quot;
  else -&gt; &quot;i don`t know..&quot;
 }

  println(reconzine(&#39;A&#39;))

  &gt;&gt;&gt;It&#39;s a letter


 -setOf를 이용한 in 사용하기

  println(&quot;Kotlin&quot; in setOf(&quot;JAVA&quot;,&quot;Scala&quot;))
  &gt;&gt;&gt;false
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[enum 과 when]]></title>
            <link>https://velog.io/@dev_ksw/enum-%EA%B3%BC-when</link>
            <guid>https://velog.io/@dev_ksw/enum-%EA%B3%BC-when</guid>
            <pubDate>Thu, 28 Oct 2021 05:06:15 GMT</pubDate>
            <description><![CDATA[<h3 id="enum">enum</h3>
<pre><code>간단하게 무지개색을 표현하는 enum class를 만들어보자

enum class Color{
  RED,ORANGE,YELLOW,GREEN,BLUE,INDIGO,VIOLET
}</code></pre><blockquote>
<ol>
<li>자바에서는 enum 이지만 코틀린에서는 enum class 이다.</li>
<li>코틀린에서 enum은 <strong>소프트 키워드</strong>라 부르는 존재다</li>
<li>코틀린은 자바와 다르게 enum에 단순히 값만 열거하는 존재가 아니고 <strong>class 이기 때문에 프로퍼티나 메소드를 정의할 수 있다.</strong></li>
</ol>
</blockquote>
<pre><code>--- enum class 프로퍼티, 메소드 예제

enum class Color(val r:Int, val g:Int, val b:Int){
    RED(255,0,0),
    ORANGE(255,165,0),
    YELLOW(255,255,0),
    GREEN(0,255,0),
    BLUE(0,0,255),
    INDIGO(75,0,130),
    VIOLET(238,130,238);

    fun rgb() = (r * 256+ g) * 256 + b
}

println(Color.BLUE.rgb())
&gt;&gt;&gt;255</code></pre><blockquote>
<p>enum class에 메소드를 정의 하는 경우 <strong>enum 상수목록과 메소드 사이에 세미콜론이 존재</strong> 하여야 한다.</p>
</blockquote>
<h3 id="when">when</h3>
<ul>
<li>자바에서 switch case 문을 이용하지만 kotlin에서는 when절을 이용해 분기 처리가 가능하다.</li>
<li>if문과 마찬가지로 when절도 식으로 만들어 낼 수 있다</li>
</ul>
<pre><code>fun getMnemonic(color:Color)=
when(color){
 Color.RED -&gt;&quot;Richard&quot;
 Color.ORANGE -&gt;&quot;Of&quot;
 Color.YELLOW -&gt;&quot;York&quot;
 Color.GREEN -&gt; &quot;Gave&quot;
 Color.BLUE -&gt; &quot;Battle&quot;
 Color.INDIGO -&gt; &quot;In&quot;
 Color.VIOLET -&gt; &quot;Vain
}

println(getMenemonic(Color.BLUE))
&gt;&gt;Battle</code></pre><blockquote>
<p>위 코드는 color로 전달된 값과 같은 분기를 찾는 코드이다.</p>
</blockquote>
<ol>
<li>when 은 자바와 달리 마지막 구문에 break를 넣지 않아도 된다.</li>
</ol>
<pre><code>----여러값을 매치 패턴으로 할 경우

fun getMnemonic(color:Color)=
when(color){
 Color.RED,Color.ORANGE,Color.YELLOW  -&gt;&quot;warm&quot; // 여러값을 구분 할때 콤마(,)로 표시
 Color.GREEN -&gt; &quot;neutral&quot;
 Color.BLUE,Color.INDIGO,Color.VIOLET -&gt; &quot;cold&quot;
}

println(getMenemonic(Color.BLUE))
&gt;&gt;cold</code></pre><blockquote>
<p>한 분기 안에서 여러값을 매치 패턴으로 사용 할 수 있으며 콤마(,)로 분리한다.</p>
</blockquote>
<ul>
<li>when은 <strong>임의의 객체를 함께 사용 가능</strong>하다.</li>
</ul>
<pre><code>----setOf를 통한 임의의 객체

fun mix(c1:Color,c2:Color) = 
when(setOf(c1,c2)){
 setOf(RED,ORANGE)  -&gt;ORANGE  
 setOf(YELLO,BLUE) -&gt; GREEN
 setOf(BLUE,VIOLET) -&gt; IDIGO
 else -&gt; throw Exception(&quot;Dirty color&quot;)
}


println(mix(Color.RED,Color.ORANGE))
&gt;&gt; ORANGE</code></pre><blockquote>
<p>위 코드에서는 c1,c2 인자값을 받아 setOf(객체)를 통해 분기 처리를 하였다.
만약 위의 조건을 성립하지 않으면 else를 타서 exception을 타게 된다.</p>
</blockquote>
<h3 id="인자-없는-when-사용">인자 없는 when 사용</h3>
<ul>
<li>when절은 인자 없이도 사용이 가능하다.<pre><code>fun mix(c1:Color,c2:Color) = 
when{
(c1 == RED &amp;&amp; c2 == YELLOW) ||
(c1 == YELLOW &amp;&amp; c2 == RED) -&gt; ORANGE
(c1 == YELLOW &amp;&amp; c2 == BLUE) ||
(c1 == BLUE &amp;&amp; c2 == YELLOW) -&gt; GREEN
(c1 == BLUE &amp;&amp; c2 == VIOLET) ||
(c1 == VIOLET &amp;&amp; c2 == BLUE) -&gt; INDIGO
else -&gt; throw Exception(&quot;Dirty color&quot;)
}

</code></pre></li>
</ul>
<p>println(mix(Color.BLUE,Color.YELLOW))</p>
<blockquote>
<blockquote>
<p>GREEN</p>
</blockquote>
</blockquote>
<pre><code>
&gt; 1. when에 아무 인자가 없으면 분기의 조건이 bool 결과를 계산하는 식이어야 한다.
2. 추가객체를 만들지 않는다는 장점은 있지만 가독성이 떨어진다.

### 스마트 캐스트 : 타입 검사와 타입 캐스트를 조합

- 간단한 산술식을 계산하는 함수를 만들어보자
</code></pre><p>interface Expr {
    class Num(val value: Int) : Expr // value 라는 프로퍼티만 존재하는 Num class
    class Sum(val left: Expr, val right: Expr) : Expr // Exper 타입의 객체라면 어떤 것이나 연산의 
    인자가 될 수 있다.
}</p>
<p>fun eval(e: Expr): Int {
    if (e is Expr.Num) {
        return e.value
    }
    if (e is Expr.Sum) {
        return eval(e.right) + eval(e.left)
    }
    throw IllegalArgumentException(&quot;Unknown expressions&quot;)
}</p>
<p>println(eval(Expr.Sum(Expr.Sum(Expr.Num(1),Expr.Num(2)),Expr.Num(4))))</p>
<blockquote>
<blockquote>
<blockquote>
<p>7</p>
</blockquote>
</blockquote>
</blockquote>
<pre><code>
&gt; **스마트 캐스트**
코틀린에서는 is를 사용해 변수타입을 검사한다. (자바에서는 instanceof)
자바에서는 instanceof로 확인한 타입에 속한 멤버를 접근하기 위해서는 명시적으로 변수 타입을 캐스팅 해야한다.
하지만 코틀린에서는 **어떤 타입인지 is로 검사하고 나면 굳이 변수를 원하는 캐스팅하지 않아도 변수가 원하는 타입으로 선언된것 처럼 사용 할 수 있는 장점이 있고 이를 프로그래머 대신 컴파일러가 캐스팅**을 해준다.

### 리팩토링 : if를 when으로 변경
</code></pre><p>fun eval(e: Expr): Int =
    when(e){
        is Expr.Num-&gt; e.value
        is Expr.Sum -&gt; eval(e.right) + eval(e.left)
        else -&gt; throw IllegalArgumentException(&quot;Unknown expressions&quot;)
    }</p>
<pre><code>&gt; when으로 분기마다 변수타입을 검사 한 후 반환값을 자동으로 스마트 캐스팅 해 줄 수 있다
가독성이 더 좋아보이는 장점이 있다.

### if와 when을 분기에서 블록 사용
</code></pre><p>  fun evalWithLogging(e: Expr): Int =
    when (e) {
        is Expr.Num -&gt; {
            println(&quot;num: ${e.value}&quot;) // 마지막 e.value 가 반환된다.
            e.value
        }
        is Expr.Sum -&gt; {
            val left = evalWithLogging(e.left)
            val right = evalWithLogging(e.right)
            println(&quot;sum : $left + $right&quot;)
            left + right   //e의 타입이 sum이면 이 식이 반환된다.
        }
        else -&gt; throw IllegalArgumentException(&quot;Unknown expressions&quot;)
    }</p>
<p> println(evalWithLogging(Expr.Sum(Expr.Sum(Expr.Num(1), Expr.Num(2)), Expr.Num(4))))</p>
<blockquote>
<blockquote>
<blockquote>
</blockquote>
<p>num: 1
num: 2
sum : 1+2
num: 4
sum : 3+4
7</p>
</blockquote>
</blockquote>
<p><del>~</del></p>
<blockquote>
<p>when절을 식으로 이용 할 땐 블록의 마지막 결과값을 반환한다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[코틀린 클래스와 프로퍼티]]></title>
            <link>https://velog.io/@dev_ksw/%EC%BD%94%ED%8B%80%EB%A6%B0-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0</link>
            <guid>https://velog.io/@dev_ksw/%EC%BD%94%ED%8B%80%EB%A6%B0-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0</guid>
            <pubDate>Wed, 27 Oct 2021 02:50:02 GMT</pubDate>
            <description><![CDATA[<h3 id="클래스">클래스</h3>
<pre><code>--- 자바 클래스
public class Person{

private final String name;

public Person(String name){
 this.name = name;
 }

public String getName(){
  return name;
}
 }


--- 코틀린 클래스
class Person(val name:String)</code></pre><blockquote>
<p>자바는 필드가 둘 이상으로 늘어나면 생성자인 본문에서 파라미터를 대입하는 대입문의 수도 늘어난다.
코틀린에서는 필드 대입 로직을 훨씬 더 적은 코드로 작성 할 수 있다.
이러한 유형의 클래스를 값 객체라 부르며 간결하게 기술 할 수 있는 구문을 제공한다.</p>
</blockquote>
<h3 id="프로퍼티">프로퍼티</h3>
<p>클래스는 자신을 이용하는 클라이언트가 데이터에 접근하는 통로로 <strong>접근자 메소드</strong>를 제공한다.
필드를 읽기 위한 게터 제공하고 필드를 변경하게 허용해야 할 경우 세터를 추가 제공 할 수 있다.
필드와 접근자를 한데 묶어 <strong>프로퍼티</strong>라고 부른다.</p>
<pre><code>코틀린 클래스 안에서 프로퍼티

class Person(
val name:String, //읽기전용 프로퍼티, 비공개 필드와 필드를 읽는 공개 게터로 만들어낸다.
val isMarried:Boolean // 변경가능한 프로퍼티, 비공개 필드, 공개 세터, 공개 게터로 만들어낸다.
)
</code></pre><ul>
<li><p>Person안에는 비공개 필드가 들어가 있고 생성자가 그 필드를 초기화 하며 게터를 통해 비공개 필드에 접근하며 자바와 코틀린이 동일하게 사용된다.</p>
</li>
<li><p><strong>자바에서 Person 클래스 사용방법</strong></p>
<pre><code>Person person =new Person(&quot;bob&quot;,true)
System.out.println(person.getName())
&gt;&gt;bob
System.out.println(person.isMarried())
&gt;&gt;true</code></pre></li>
<li><p><strong>코틀린에서 Person 클래스 사용방법</strong></p>
<pre><code>val person = Person(&quot;bob&quot;,true) // new 키워드를 사용하지 않고 생성자를 호출한다.
println(person.name) //프로퍼티 이름을 직접 사용해도 코틀린이 자동으로 게터를 호출해준다.
&gt;&gt;bob
println(person.isMarried)
&gt;&gt;true</code></pre></li>
</ul>
<h3 id="커스텀-접근자">커스텀 접근자</h3>
<p>프로퍼티의 접근자를 직접 작성 할 수 있다.</p>
<pre><code> 다음 예시는 사각형 클래스를 정의 하면서 자신이 정사각형인지 확인 여부를 알 수 있는 코드이다.

 class Rectangle(val height:Int,val width:Int){
    val isSquare:Boolean
    get() {   //프로퍼티 게터 선언
       return height == width
    }
    //또는 get() = height== width로 구현이 가능
}</code></pre><blockquote>
<ol>
<li>isSqaure 프로퍼티에는 자체 값을 저장하는 필드가 필요 없다.</li>
<li>이 프로퍼티에는 구현을 제공 하는 게터만 존재한다.</li>
<li>클라이언트가 isSquare 프로퍼티에 접근 할 때 마다 프로퍼티 값을 매번 계산한다.</li>
</ol>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[코틀린 함수와 변수]]></title>
            <link>https://velog.io/@dev_ksw/%EC%BD%94%ED%8B%80%EB%A6%B0-%ED%95%A8%EC%88%98%EC%99%80-%EB%B3%80%EC%88%98</link>
            <guid>https://velog.io/@dev_ksw/%EC%BD%94%ED%8B%80%EB%A6%B0-%ED%95%A8%EC%88%98%EC%99%80-%EB%B3%80%EC%88%98</guid>
            <pubDate>Tue, 26 Oct 2021 05:53:48 GMT</pubDate>
            <description><![CDATA[<h3 id="hello-world">Hello world</h3>
<pre><code>fun main(args: Array&lt;String&gt;){
   println(&quot;Hello World&quot;)
}</code></pre><ul>
<li>함수선언을 할때 <strong>fun 키워드</strong> 이용한다.</li>
<li>파리미터 : 파라미터 이름 뒤에 타입을 쓴다. <code>(args : Array&lt;String&gt;)</code></li>
<li>자바와 달리 <strong>함수를 최상위 수준에 정의</strong> 할 수 있다. class안에 함수를 넣어야 할 필요가 없다.</li>
<li>배열도 일반적인 클래스와 마찬가지다.</li>
<li>코드 끝에 세미콜론(;)을 넣을 필요가 없다.</li>
</ul>
<h3 id="기본-함수">기본 함수</h3>
<pre><code>fun max(a:Int,b:Int):Int{
   return if(a&gt;b) a else b
}</code></pre><ul>
<li>함수는 fun 키워드 그 뒤에 함수 이름이 온다 그리고 괄호를 열어 파라미터 목록이 온다. 
그리고 그 뒤에는 :Type 을 넣어 반환할 타입을 정한다. 
<code>fun max(a:Int,b:Int):Int</code></li>
<li>함수 본문은 반환 할 식에 대해서 작성한다.
<code>{ return if(a&gt;b) a else b }</code></li>
<li>코틀린은 함수를 본문이 아닌 식으로 쓸 수 있다.<blockquote>
<p>코틀린의 if는 문이 아니라 식이다. (물론 문으로도 활용 가능하다)
식은 값을 만들어 내며 다른 식의 하위 요소로 계산에 참여 할 수 있는 반면
문은 자신을 둘러싸고 있는 가장 안쪽 블록의 최상위 요소로 존재하며 아무런 값을 만들어내지 않는다는 차이가 있다.</p>
</blockquote>
<pre><code>위 예제를 식으로 변경하면 
fun max(a:Int,b:Int) = if(a&gt;b) a else b
로 이용 할 수 있다.</code></pre></li>
<li>타입추론을 통해 컴파일러가 타입을 분석해 프로그래머 대신 프로그램 구성 요소 정해준다.</li>
</ul>
<h3 id="변수">변수</h3>
<ul>
<li><p>자바와 반대로 변수를 타입(자료형 또는 클래스) 선언을 앞이 아닌 뒤에 선언해준다.</p>
</li>
<li><p>코틀린은 타입 생략이 가능하다. 대신 초기화값을 입력 해야 한다.</p>
<pre><code>val a = &quot;가나다라마바사&quot; //타입 생략
val a:String = &quot;가나다라마바사&quot; // 타입 명시</code></pre><blockquote>
<p>식이 본문인 함수와 마찬가지로 컴파일러가 초기화 식을 분석해서 타입 추론을 해준다.</p>
</blockquote>
</li>
<li><p>변경 가능한 변수와 변경 불가능한 변수로 나뉜다.</p>
<blockquote>
<ol>
<li>val(값을 뜻하는 value에서 따옴): 
a. 변경 불가능한 참조를 저장하는 변수
b. 초기화가 되면 재 대입이 불가능하다.
c. 자바로 따지면 final 변수</li>
<li>var(변수를 뜻하는 variable에서 따옴):
a. 변경 가능한 참조다.
b. 변수의 값을 바꿀 수 있다.
c. 자바의 일반 변수에 해당 된다.
```</li>
</ol>
</blockquote>
</li>
<li><p>val 변수는 블록을 실행 할 때 한번만 초기화 되어야 한다. 조건에 따라 val 값을 다른 여러 값으로 초기화 할 수 있다.</p>
<p>val message :String
if(true){
 message = &quot;abcd&quot; 
} else{
message + &quot;efgh&quot;
}</p>
</li>
<li><p>val 참조 자체는 불변일지라도 객체의 내부 값은 변경이 가능하다.
val a = arrayList(&quot;a&quot;,&quot;b&quot;,&quot;c&quot;) //불변 참조를 선언
a.add(&quot;d&quot;) //참조가 가리키는 객체 내부를 변경</p>
<pre><code></code></pre></li>
</ul>
<h3 id="문자열-템플릿">문자열 템플릿</h3>
<p>코틀린에서 키워드 $를 통해 변수를 문자열 안에 이용이 가능하다.</p>
<pre><code>val a = &quot;world&quot; println(&quot;hello $a&quot;)
result = hello world</code></pre><p><strong>$문자를 문자열에 넣고 싶으면 $ 앞에 \를 삽입해야 한다.</strong></p>
<blockquote>
</blockquote>
<ol>
<li>복잡한 식은 {} 중괄호를 이용해서 문자열 템플릿안에 넣을 수 있다.
ex) val apple = Apple()
println (&quot;apple color = ${apple.color()})</li>
<li>한글 문자열 템플릿에서는 유니코드 변수 이름으로 인해 컴파일러가 오류를 내놓을 수 있다.
한글 문자열 변수를 중괄호에 넣어서 이용하는게 좋다.
ex) val hello =&quot;안녕하세요&quot;
println(&quot;korean hello = ${hello}) </li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[코틀린 코드 컴파일 ]]></title>
            <link>https://velog.io/@dev_ksw/%EC%BD%94%ED%8B%80%EB%A6%B0-%EC%BD%94%EB%93%9C-%EC%BB%B4%ED%8C%8C%EC%9D%BC</link>
            <guid>https://velog.io/@dev_ksw/%EC%BD%94%ED%8B%80%EB%A6%B0-%EC%BD%94%EB%93%9C-%EC%BB%B4%ED%8C%8C%EC%9D%BC</guid>
            <pubDate>Tue, 26 Oct 2021 02:02:43 GMT</pubDate>
            <description><![CDATA[<h3 id="코틀린-컴파일">코틀린 컴파일</h3>
<ul>
<li>코틀린 소스코드의 확장자는 파일명.kt 이다.</li>
<li>컴파일 할 때 코틀린 소스코드를 분석해서 .class 파일을 만든다.</li>
<li>코틀린 컴파일러로 컴파일 한 코드는 코틀린 런타임 라이브러리에 의존한다.</li>
<li>코틀린으로 컴파일 한 애플리케이션을 배포 할 때는 런타임 라이브러리도 함께 배포한다.</li>
<li>메이븐(maven), 그레들(gradle), 앤트(ant) 등의 빌드 시스템을 이용한다.</li>
</ul>
<p><img src="https://images.velog.io/images/dev_ksw/post/64455ccd-43eb-4fb0-8d10-49078e96d6b6/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Kotlin 언어 요약😀]]></title>
            <link>https://velog.io/@dev_ksw/Kotlin-%EA%B8%B0%EC%B4%88-%EC%9A%94%EC%95%BD</link>
            <guid>https://velog.io/@dev_ksw/Kotlin-%EA%B8%B0%EC%B4%88-%EC%9A%94%EC%95%BD</guid>
            <pubDate>Fri, 22 Oct 2021 04:54:41 GMT</pubDate>
            <description><![CDATA[<h3 id="코틀린-언어-특징-요약">코틀린 언어 특징 요약</h3>
<ul>
<li>코틀린은 타입추론을 지정하는 <strong>정적 타입 언어</strong>이다.</li>
<li>객체지향과 함수형 프로그래밍을 모두 지원한다.<blockquote>
<p>1.일급 시민 함수를 이용해 추상화가 가능하다.
2.불변 값 지원을 통해 다중 스레드 애플리케이션 개발과 테스트를 쉽게 할 수 있다.</p>
</blockquote>
</li>
<li>런타임 라이브러리는 크기가 작고, 코틀린 컴파일러는 안드로이드 API를 특별히 지원 한다.</li>
<li>코틀린은 무료 오픈 소스이다. 주요 IDE(IntelliJ ,Eclipse, 안드로이드 스튜디오)와 빌드 시스템을 완전히 지원한다.</li>
<li>실용적이며, 안전하고, 간결하며 상호운용성이 좋다.<blockquote>
<ol>
<li>코틀린 설계는 일반적인 작업에 대해 잘 알려진 해법을 채택 했다. </li>
<li>NullPointerException 오류를 방지한다.</li>
<li>읽기 쉽고 간결한 코드를 지원하면서 자바와 아무런 제약 없이 통합 될 수 있다.</li>
</ol>
</blockquote>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Kotlin 언어의 장점👍]]></title>
            <link>https://velog.io/@dev_ksw/Kotlin%EC%9D%98-%EC%9E%A5%EC%A0%90</link>
            <guid>https://velog.io/@dev_ksw/Kotlin%EC%9D%98-%EC%9E%A5%EC%A0%90</guid>
            <pubDate>Thu, 21 Oct 2021 08:28:12 GMT</pubDate>
            <description><![CDATA[<h3 id="실용성">실용성</h3>
<ul>
<li>자바의 코드 스타일을 동일하게 이용 할 수 있지만, 코틀린언어의 특성을 잘 활용하여 간결하고, 문제를 해결하기 위해 만들어진 실용적인 언어다.</li>
<li>젯브레인사의 IntelliJ IDE를 이용하면 간결한 구조로 바꿀 수 있는 코드 패턴을 자동적으로 감지해서 수정을 제시 한다. 이를 통해 코틀린 언어의 특성을 이해할 수 있다.</li>
</ul>
<h3 id="간결성">간결성</h3>
<ul>
<li>코틀린은 자바에 비해 코드가 간결하다.</li>
<li>getter,setter, 생성자 파라미터를 필드에 대입하기 위한 로직을 묵시적으로 제공한다.(data class)</li>
<li>자바에서는 컬렉션에서 원소를 찾는 함수를 명시적으로 작성해야만 하는 코드의 양이 상당하지만 코틀린의 컬렉션 라이브러리 함수로 대처 할 수 있다.(collection function)</li>
<li>람다를 지원하기 때문에 작은 코드 블록을 라이브러리 함수에 쉽게 전달 할 수 있다.</li>
</ul>
<h3 id="안전성">안전성</h3>
<ul>
<li><p>코틀린은 jvm에서 실행되는 정적 타입 언어이며, 타입 안전성을 보장한다.</p>
<blockquote>
<p>jvm은 
메모리 안전성을 보장한다.
버퍼 오버플로우를 방지한다.
동적으로 할당한 메모리를 잘못 사용함으로써 인해 생길 수 있는 문제를 예방 할 수 있다.</p>
</blockquote>
</li>
<li><p>코틀린의 타입 시스템은 null이 될 수 없는 추적하며, NullPointerExeception 발생 할 수있는 연산을 사용하는 코드를 금지한다. </p>
<pre><code>? 선언으로 nullable이 가능함

val s:String?=null //널이 가능
val s2:String =&quot;&quot; //널이 불가능</code></pre></li>
<li><p>ClassCast으로 ClassCastException을 방지해주며, 타입 검사와 캐스트를 한 연산자에 의해 이뤄진다.</p>
<pre><code>if(value is String)
 println(value.toUpperCase)</code></pre><h3 id="상호운용성">상호운용성</h3>
</li>
<li><p>코틀린은 기존 자바의 라이브러리, 메소드 호출, 상속, 인터페이스, 어노테이션 등을 모든걸 이용 할 수 있다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Kotlin 언어 주요 특징😜]]></title>
            <link>https://velog.io/@dev_ksw/Kotlin-%EC%A3%BC%EC%9A%94-%ED%8A%B9%EC%A7%95</link>
            <guid>https://velog.io/@dev_ksw/Kotlin-%EC%A3%BC%EC%9A%94-%ED%8A%B9%EC%A7%95</guid>
            <pubDate>Wed, 20 Oct 2021 09:26:00 GMT</pubDate>
            <description><![CDATA[<h3 id="코틀린은-자바가-실행되는곳-모든-플랫폼에-적용이-가능">코틀린은 자바가 실행되는곳 모든 플랫폼에 적용이 가능.</h3>
<ul>
<li>대표적으로 서버(spring), 안드로이드 플랫폼 적용가능</li>
</ul>
<h3 id="정적-타입-지정-언어">정적 타입 지정 언어</h3>
<ul>
<li>자바와 마찬가지로 코틀린도 정적타입 언어(객체의 필드나 메소드를 사용 할때 <strong>컴파일러가 타입을 입증</strong>)</li>
<li>코틀린은 자료형을 명시 할 필요 없이 <strong>변수 타입을 자동으로 유추</strong> 가능. (타입 추론)<pre><code> var count = 0</code></pre></li>
<li><strong>정적 타입 지정의 장점</strong><blockquote>
<p><strong>1. 성능</strong> : 실행 시점에 어떤 메소드를 호출 할지 알아내는 과정이 필요 없으므로 메소드 호출이 더 빠름</p>
</blockquote>
</li>
<li><em>2. 신뢰성*</em> : 컴파일러가 정확성을 검증하기 떄문에 프로그램 오류로 중단될 가능성이 적어짐</li>
<li><em>3. 유지 보수성*</em> : 객체가 어떤 타입인지 알 수 있기 때문에 코드 다룰 때도 쉬워짐</li>
<li><em>4. 도구 지원*</em> : 도구(IDE,Web)를 통해 정확한 코드 완성을 제공해줘 더 안전하게 리팩토링이 가능하다.</li>
</ul>
<h3 id="함수형-프로그래밍-이용">함수형 프로그래밍 이용</h3>
<ul>
<li><strong>일급객체 함수</strong>: 함수를 일반 값처럼 다룰 수 있다.<blockquote>
<p><strong>일급객체 함수 조건 :</strong></p>
</blockquote>
</li>
</ul>
<p>1.함수를 변수에 저장할 수 있음.
2.함수를 인자로 다른 함수에 전달 할 수 있어야함
3.함수에서 새로운 함수를 만들어서 변환 가능.</p>
<ul>
<li><p><strong>불변성</strong> : 함수가 만들어지면 내부 상태가 절대로 바뀌지 않는 불변 객체를 사용해 프로그램을 작성한다.</p>
</li>
<li><p><strong>부수 효과 없음</strong> : 입력이 같으면 항상 같은 출력을 내놓고 다른 객체의 상태를 변경하지 않고, 함수 외부나 다른 바깥 환경과 상호작용하지 않는 순수 함수를 이용 한다.</p>
</li>
<li><p><strong>함수형 프로그래밍의 장점</strong> :</p>
<blockquote>
<p><strong>1. 간결성</strong> : 함수를 값처럼 활용할 수 있으며 더 강력한 추상화를 할 수 있고 이를 사용 해 코드 중복을 막을 수 있다.</p>
</blockquote>
</li>
<li><p><em>2. 다중 스레드를 사용해도 안전하다*</em> : 불변 데이터 구조를 사용하고 순수 함수를 데이터 구조에 적용한다면 같은 다중 스레드 환경에서 같은 데이터를 여러 스레드가 변경 할 수 없음. 따라서 복잡한 동기화를 적용하지 않아도 된다.</p>
</li>
<li><p><em>3. 테스트 용이 *</em> : 부가적인 함수 없이 순수함수로 독립적으로 테스트가 가능하다.</p>
<pre><code>  -순수 함수 예시-
  fun findAlice() = findPerson{it.name ==&quot;Alice&quot;} 
  fun findBob() = findPerson{it.name ==&quot;Bob&quot;}
</code></pre></li>
</ul>
<pre><code>
### 무료오픈소스
- 코틀린 언어와 컴파일러, 라이브러리 및 코틀린 관련된 모든 도구는 무료로 이용이 가능하고 아파치2 라이선스하에 제공 된다. 개발은 github을 통해 이뤄지고 있으며, 인텔리 제이, 이클립스 같은 오픈소스 IDE를 활용 할 수 있다.

</code></pre>]]></description>
        </item>
    </channel>
</rss>