들으면서 JAVA의 static이 생각났다.

singleton 패턴의 경우 예전에 글로 읽기만 하고 실제로 구현해 본 적은 없어서 잘 와닿지는 않았지만

JAVA의 static처럼 어디에서든지 접근할 수 있다는 .. 대충 그런 개념인 것 같다.

일단 나는 object는 static class와 비슷하고, companion object는 해당 클래스 내의 static 변수를 모아놓은..? 거라고 이해하였다.

 


1. object 

fun main() {
    println(Counter.count)
    Counter.countUp()
    Counter.countUp()
    
    println(Counter.count)
    
    Counter.clear()
    
    println(Counter.count)
}

object Counter {
    var count = 0
 
    fun countUp() {
        count++
    }
    
    fun clear() {
        count = 0
    }
}
<실행결과>
0
2
0

object로 Counter를 선언한다. Counter의 경우 countUp이 선언되면 count가 1씩 증가하도록 하였다.

사용할 때는 자바의 static class처럼 Counter.XX()의 방식으로 사용한다.

자바의 static class처럼 남용하면 문제가 생기겠지..?

 

 

2. companion object

class FoodPoll(val name:String) {
    companion object {
        var total = 0
    }
    
    var count = 0
    
    fun vote() {
        total++
        count++
    }
}


fun main() {
    var a = FoodPoll("cake")
    var b = FoodPoll("cookie")
    
    a.vote()
    a.vote()
    b.vote()
    b.vote()
    b.vote()
    
    println("RESULT :: ${a.name} (${a.count}) vs ${b.name} (${b.count}) => ${FoodPoll.total}")
}
<실행결과>
RESULT :: cake (2) vs cookie (3) => 5

companion object는 object와 마찬가지로 어디에서나 접근이 가능하나 특정 클래스 내에 속해있다는 것에서 object와 차이점을 보인다. 자바로 생각하자면 static 변수와 비슷하지 않을까?

 

main()에서 FoodPoll 객체 두 개를 만든다음 vote()를 다섯 번 실행한다.

vote()는 해당 객체의 count와 companion object인 total을 1씩 증가하는 함수이다. 

 

실행 결과를 보면 a와 b객체의 count는 각각 vote를 호출한 횟수이고 total은 그 합과 같다는 것을 알 수 있다.

 

companion object를 사용할 때 주의할 점이 있는데,

JAVA의 static 변수의 경우 클래스로 생성한 객체에서도 해당 static변수를 참조연산자를 통해 가져올 수 있는 반면

compainion object의 경우 객체의 참조연산자를 통해서 가져오는 경우 컴파일 에러가 발생한다.

 

예를 들어 FoodPoll의 객체인 icecream이 있다고 할 때

자바는 아래 두 경우 모두 사용할 수 있지만
(물론 뭐라고 메세지를 띄우기는 한다)

int total2 = FoodPoll.total	//가능
int total = icecream.total;			//가능

코틀린에서는 'Unresolved reference'이라며 에러를 발생시키는 것을 확인할 수 있다.

var t1 = FoodPoll.total	//가능
var t2 = a.total	//불가능 (Unresolved reference: total)

나중에 기본서를 한번 더 읽으면서 내가 이해한 게 맞는지 꼭 확인해야 할 것 같다.

지금은 그냥.. '앗 이 맛은.... static의 맛과 비슷하구나..!' 하는 느낌이라..

지금 그냥 맛보기만 하는 수준이라서 더 그런 것 같기도 하고..?

'개발 > Kotlin' 카테고리의 다른 글

코틀린 공부 - 함수(2)  (0) 2021.08.02
코틀린 공부 - 함수(1)  (0) 2021.08.02
코틀린 기초 - 4(고차함수, 람다)  (0) 2020.06.24
코틀린 기초 - 3 (if~else, when)  (0) 2020.06.23
코틀린 기초 - 2 (배열, 반복문)  (0) 2020.06.16

코딩메이트 디모님의 강좌를 기반으로 하여 학습한 내용입니다  > 보러가기 <

 

 

람다함수는 이전부터 써 왔던 거라 별로 어렵지는 않았는데.. 

뭐랄까.. 이번에 공부하면서 JAVA에서 처음으로 interface를 이용한 콜백함수 구현을 처음 알았을 때의 그런 '???' 스러움을 다시 느꼈다. 

'뭐..? 함수 파라미터에 함수를 넣을 수 있어..?'

 

1. 반환값이 없는 함수의 경우

fun main() {
    call(::printOnly)
}

fun call(function:(String) -> Unit) {
    function("Call")
}

fun printOnly(str:String) {
    println("Print Only] > $str")
}
<출력결과>
Print Only] > Call
lambda] > Call

printOnly 함수는 String을 인자로 받는 void형 함수이다.

call 함수는 String을 인자로 받는 void형 함수를 인자로 받는 함수이다.

함수 실행 시 인자값으로 함수를 넘길 때는 ::{함수명} 을 입력해야 한다.

그냥 입력하면 해당 함수의 결과값을 사용한다는 의미라서 에러메세지가 나옴.

 

call함수를 호출하면 call 함수 내부에서 인자로 전달된 printOnly 함수를 실행하게 된다.

 

이 때 미리 선언한 함수가 아니라 람다 함수를 변수로 선언하여 사용할 수도 있다. 아래 예시 참조.

    var lambda:(String)->Unit = {str -> println("lambda] > $str")}
    call(lambda)

 

2. 반환값이 있는 경우

fun main() {
    call2(::returnValue)
}

fun call2(function:(String, Int, Int) -> Int) {
    var sum = function("Call2", 2, 3)
    println("SUM :: " + sum)
}

fun returnValue(str:String, i:Int, j:Int):Int {
    println("returnText] > $str")
    return i+j
}
<출력결과>
returnText] > Call2
SUM :: 5
test] > Call2
SUM :: 5

1번과 별반다르지 않다.

returnValue는 인자로 받은 String을 화면에 출력하고 Int들을 더한 값을 반환하는 함수이다.

call2는 인자로 받은 함수를 실행하고 그 결과를 받아 화면에 출력하는 함수이다.

처음 공부할 때 프로그램이 어떻게 실행되는지 코드를 따라가며 확인하는 게 좋을 것 같다.

 

단, 1번과는 다르게 람다함수에서는 return을 허용하지 않기 때문에 이 경우에는 람다함수 말고 익명함수를 통해 구현할 수 있다.  가능하다 으아아아아아아아아 !!! 가능해!!!! 다음 강의에서 바로 처음부터 나오더라!!!!

 

  1) 람다 함수 사용 : 람다 함수의 마지막 줄이 반환값

   var lambda:(String, Int, Int)-> Int = { str, i, j -> 
           println("lambda] > $str")
           i+j
   }
   
   call2(lambda)

 

  2) 익명 함수 사용 : return으로 반환값을 명시

    val func = fun(s:String, i:Int, j:Int):Int {
         println("test] > $s")
         return i+j
    }
    call2(func)

 

 

 

3. 기타

1) 인자를 받지 않는 경우

val lambda_empty:()->Unit={println("EMPTY LAMBDA")}

lambda_empty()
<실행 결과>
EMPTY LAMBDA

인자를 받지 않는 경우 그냥 실행할 코드만 넣어준다.

 

 

2) 인자가 하나인 경우

인자가 하나인 경우 따로 명시하지 않고 it을 사용해서 파라미터를 사용할 수 있다.

아래 코드는 둘 다 동일한 결과를 보임. (lambda_it에서 str이라는 변수에 한번 더 할당했는데, 그럴 필요 없이 it으로 사용해도 된다.

val lambda_nor:(String)->Unit={
	str-> println("print $str")
}

val lambda_it:(String)->Unit={
	var str:String = it
    println("print $str")
}

오늘 갑자기 모르는 내용이 확 나와서

나는 내가 강의를 빼먹었나? 하고 있었는데

다행히 그건 아니었다.

 

영상만 볼 때는 뭐가 뭔지 잘 몰랐는데

직접 만들다보니 어느정도 이해가 가는 것 같기도 하고..

알다가도 모르겠다 :(

'개발 > Kotlin' 카테고리의 다른 글

코틀린 공부 - 함수(1)  (0) 2021.08.02
코틀린 기초 5 - object  (0) 2020.06.25
코틀린 기초 - 3 (if~else, when)  (0) 2020.06.23
코틀린 기초 - 2 (배열, 반복문)  (0) 2020.06.16
코틀린 기초 - 1  (0) 2020.06.16

유튜브의 '센치한개발자' 채널의 코틀린 강의를 들으면서 하는 벼락치기 공부입니다!

기본적인 부분은 유튜브 강의로 보고 나서 3년 전에 산 책 한 번 더 읽어야겠다..

 

 

 

1. 배열(listOf) + 반복문(for)

fun main() {
    var arr = listOf("가", "나")	//변경 불가능한 배열
    
    //기본 반복문
    for(item in arr) {
        println(item);
    }
}
<코드 실행 결과>
가
나

listOf로 생성한 배열은 구조를 변경할 수 없다.

즉 JAVA의 Array와 비슷하다고 볼 수 있겠다.

 

반복문의 경우 for을 사용했는데, 

자바의 foreach문(향상된 반복문)과 비슷한 모양새를 하고 있다.

 

2. 배열(mutableListOf()) + 반복문 (for ... withIndex())

fun main() {
    var arr2 = mutableListOf("A", "B")	//변경 가능한 배열

    //index 값 가져오는 배열문
    for((index, item) in arr2.withIndex()) {
        println("$index / $item");
    }
}
<코드 실행 결과>
0 / A
1 / B

mutableListOf() 로 생성한 배열은 구조를 변경할 수 있다. (add(), remove())

즉 JAVA의 LIST와 비슷하다고 볼 수 있다.

 

이 코드에서 쓰인 for문은 첫번째 것과 모양이 비슷하면서 다른데

첫 번째 반복문은 단순히 안에 들어있는 값만 가져오면 될 때 쓴다면

이건 현재 몇 번째 실행중인지에 대한 index값을 가져오려 할 때 사용할 수 있다.

 

 

 

 


이전부터 생각했지만 코틀린이라는 녀석.. 굉장히 대충대충(?)인 느낌인 게..

String이든 Int든 일단 val아니면 var로 때웠는데

이번에 배열 선언할 때도 기대를 저버리지 않고(?) var 또는 val를 이용하여 선언할 수 있다는 걸 볼 수 있다.

게으른 개발자를 위해서인걸까...?

'개발 > Kotlin' 카테고리의 다른 글

코틀린 공부 - 함수(1)  (0) 2021.08.02
코틀린 기초 5 - object  (0) 2020.06.25
코틀린 기초 - 4(고차함수, 람다)  (0) 2020.06.24
코틀린 기초 - 3 (if~else, when)  (0) 2020.06.23
코틀린 기초 - 1  (0) 2020.06.16

코틀린이 나오고 안드로이드의 공식 언어로 채택된 지도 꽤 시간이 흘렀으나 이제야 공부하게 된 나 자신을 반성 또 반성.. 늦게나마 공부를 시작하게 되었다.

일단 올해 내로 공공 API를 사용하는 앱을 만들어 서비스하는 것을 목표로 열심히 해 보기로..

------------

이번 시간에는 기본 변수형의 차이에 대한 차이를 학습하였다.

 

1. val 변수 (value)

fun main() {
    val first = "Hello"	//변경 불가능한 변수
    
    println(first)
	//first = "Hello2"	//변경 불가(에러)

}
<코드 실행 결과>
Hello

val 은 Java의 fianl 변수와 대응하며, 값이 한 번 할당되면 이를 변경할 수 없다.

위의 코드에서 fist = "hello2" 부분을 주석해제하면 에러가 발생하게 된다.

 

2. var 변수 (variable)

fun main() {
    var second:String = "TEST";
    var third:String? = null
    
    println(second)
    second = "WORLD"
    println(second)

    println(third)
}
<코드 실행 결과>
TEST
WORLD
null

var 은 일반적인 변수로, 값을 여러 번 할당할 수 있다.

자료형 뒤에 ? 가 붙으면 해당 변수에 null을 할당할 수 있다는 것을 의미한다.

 

사실 꼭 초기값을 할당해주지 않고 var {변수명}:{자료형} 으로 쓸 수 있다.

var number:Int

 

3. 함수(function)

fun main() {
    var third:String? = null
    
    println(third)
    third = getString()
    println(third)
    third = getSum(2, 5)
    println(third)

    end()
}

fun getString() : String {
    return "GET STRING FROM METHOD";
}

fun getSum(i : Int, i2 : Int) : String {
    return "get Sum (" + i + " + " + i2 + " = " + (i+i2) + ")"
}

fun end() {
    println("end of line")
}
<코드 실행 결과>
null
GET STRING FROM METHOD
get Sum (2 + 5 = 7)
end of line

함수 선언 시 fun 이라는 키워드를 사용한다.

반환값이 있는 경우 (getString(), getSum()) 변수 선언 시와 마찬가지로 함수명 뒤에 자료형을 적어주고, 반환값이 없는 경우에는 이를 생략할 수 있다. 

JAVA와의 차이라면 자료형이 앞에 위치하냐 뒤에 위치하냐의 차이가 아닌가 싶다.

'개발 > Kotlin' 카테고리의 다른 글

코틀린 공부 - 함수(1)  (0) 2021.08.02
코틀린 기초 5 - object  (0) 2020.06.25
코틀린 기초 - 4(고차함수, 람다)  (0) 2020.06.24
코틀린 기초 - 3 (if~else, when)  (0) 2020.06.23
코틀린 기초 - 2 (배열, 반복문)  (0) 2020.06.16

+ Recent posts