본문 바로가기
개발 지식/Kotlin

[Kotlin] Kotlin 기초 - 03 (스코프 /고차 람다 함수)

by 에르주 2022. 5. 16.
반응형

2022.04.27 - [개발 지식/Kotlin] - [Kotlin] Kotlin 기초 - 02

 

[Kotlin] Kotlin 기초 - 02

2022.04.24 - [개발 지식/Kotlin] - [Kotlin] Kotlin 기초 -01 [Kotlin] Kotlin 기초 -01 1. 변수 선언 : var , val - var : 선언 후 수정 가능 - val: 선언 후 수정 불가능 (Java에서 final과 같은 역할을 한다.)..

erjuer.tistory.com

 

1. 코틀린의 프로젝트 구조

 

1) 코틀린은 클래스명과 파일명이 일치하지 않아도 된다.

2) 하나의 파일에 여러개의 클래스를 넣어도 알아서 컴파일이 가능하다. 파일이나 폴더를 기준으로 하지않고 파일내에 있는 패키지 단위로 구분하기 때문이다.

 

 

2. 변수, 함수, 클래스 접근 범위와 접근 제한자

 

코틀린의 스코프와 범위는 다음과 같다.

스코프.?
: 변수나 함수 클래스 같은 멤버들을 서로 공유하여 사용할 수 있는 범위를 지정해둔 단위

범위
: 패키지, 클래스, 함수

 

 

var a = "맛있는 것은 참을수 없어"
var b = "패키지 스코프"


class B {
    var b = "클래스 스코프"
    fun println() {
        println(a)
    }
}

fun main() {
    println(a)
    B().println()

    val b ="함수 스코프"
    println(b)
}

이 코드에서

 

변수 a는 패키지 스코프에 선언하였고

변수 b는 패키지 스코프, 클래스 스코프 , 함수 스코프에 각각에 선언하였다. 즉 하위 스코프에서 상위 스코프의 멤버를 재정의 할 수 있다.

스코프 실행 결과

 

1) 스코프 외부에서는 스코프 내부의 멤버를 참조 연산자로만 참조가 가능하다

  • println(a)로 참조하였다.

2) 하나의 패키지에서 다른 패키지의 멤버를 참조할 때도 import를 사용하거나 직접 참조 연산자를 사용한다.

  •  Kotlin은 패키지 단위로 구분하기 때문에 패키지 단위의 import로 사용 가능하다.

3) 동일 스코프 내에서는 멤버들을 공유할 수 있다.

  • 패키지 스코프에서 정의한 var a ="맛있는 것은 참을 수 없어" 값을 main 함수에서 println(a)로 출력시 a값이 정상적으로 출력된다.

4) 하위 스코프에서는 상위 스코프의 멤버를 재정의 할 수 있다.

  • b값을 main함수에서 "함수 스코프"로 재정의 하였으며 출력결과 b의 값이 바뀐 것을 확인 할 수 있다.

5) 스코프의 같은 레벨에서는 같은 이름의 멤버가 선언되어서는 안된다.

  • Conflicting declarations 에러 발생

Conflicting declarations

 

 

 

3. 고차 함수와 람다 함수

 

고차 함수

 

- 함수를 마치 클래스에서 만들어낸 인스턴스처럼 취급하는 방법

- 함수를 파라미터로 넘겨 줄수도 있고 결과값으로 받을 수도 있는 방법

 

예를 들어 eat라는 함수는 파라미터값을 String으로 받아 그 값을 이용하여 println을 수행한다고 해보자.

fun eat(food: String) {
   println("$food 먹었습니다.")
}

 

meat 함수는 파라미터를 함수값으로 받는 함수이다. (단, 반환형이 없는 함수) 즉 고참함수를 활용하게 되는데  파라미터 값으로 반환형이 없는 eat 함수를 받아 실행해보면

fun meat(function: (String) -> Unit) {
    function("돼지고기 삼겹살을")
}


fun main() {
  meat(::eat)
}

// 결과값
// 돼지고기 삼겹살을 먹었습니다.

 

 

더 나아가서 반환형이 있는 함수를 파라미터로 받았을 때에는 어떻게 처리가 될까?

 

group 함수는 파라미터를 고차함수로 받아 처리하는 함수이다. 입력값이 String, 반환값이 String 인 함수를 받아 처리해보도록 한다.

 

music 함수는 groupName을 받아 조건문 처리 후 String 값을 반환하는 함수이다.

fun group(function: (String) -> String) {

    var music_detail = function("멜로망스")
    println(music_detail)
}

fun music(groupName : String) : String{

    if(groupName.equals("멜로망스"))
        return groupName + "의 동화라는 노래는 참 좋다"
    return "해당 그룹의 노래를 잘 모르겠습니다."
}

fun main() {
    // 고차 함수 형태로 넘기려면 함수이름 앞에 콜론을 두개 붙여주면 된다.
	group(::music)
}

// 결과값
// 멜로망스의 동화라는 노래는 참 좋다

 

 

람다 함수

 

일반 함수와 달리 그 자체가 고차 함수 이기 때문에 별도의 연산자 없이도 담을 수 있다.

위에서 예시를 들었던 것들을 람다 함수로 표현 해보자.

fun meat(function: (String) -> Unit) {
    function("돼지고기 삼겹살을")
}

fun eat(food: String) {
   println("$food 먹었습니다.")
}

fun main() {

    // String -> Unit : 파라미터를 String으로 받는다. 그리고  반환값이 없다.
    // 파라미터 (str) -> println 실행
    val eat: (String) -> Unit = {str -> println("$str 먹었습니다.")}
    meat(eat)
    
    // 결과
    // 돼지고기 삼겹살을 먹었습니다.
}

또한 파라미터가 하나 뿐이라면 it을 사용할 수도 있다. (결과 동일)

var eat_it: (String) -> Unit  = { println("$it 먹었습니다")}
meat(eat_it)

 

eat_lambda에서는 (String) -> Unit 으로 명시해주어야 하지만 앞에 (String) 으로 자료형이 추론되므로 생략할 수 있다.

val eat_lambda = {str:String -> println("$str 먹었습니다.")}
meat(eat_lambda)

// 결과
// 돼지고기 삼겹살을 먹었습니다.

위와 같이 타입 추론을 이용하여 좀 더 축약해서 표현이 가능하다.

 

 

끝.

 

참고자료

https://www.youtube.com/channel/UCVqKQvma-Cr-eQ4hgxETAFQ

 

테크과학! DiMo

개발자가 얘기하는 생활 속 IT기술에 대한 과학! 여러분이 몰랐던, 혹은 정확히 알지 못했던 IT 테크놀러지를 파드립니다! 좋은 영상을 위한 채널 후원, 투네이션을 통해서 해주세요! 후원링크 htt

www.youtube.com

 

 

 

 

 

 

 

반응형

댓글