-
[코틀린 완벽 가이드] 3장 함수 정의하기 (3.1 함수)코틀린 공부/코틀린 2023. 12. 28. 10:32
여기서는 함수의 기본적인 내부 구조를 살펴보고 인자(named argument), 디폴트(default) 값, vararg 스타일 함수 등을 살펴본다. 그리고 코틀린 언어의 명령형(imperative) 제어 구조도 다룬다.
배우는 내용 :
- 코틀린 함수의 구조
- 제어 구조 : 조건문, 루프, 오류 처리
3.1 함수
3.1.1 코틀린 함수의 구조
반지름이 주어졌을 때 원의 넓이를 계산하는 함수를 정의
fun circleArea(radius: Double) : Double{ return PI*radius*radius } fun main() { println(circleArea(3.0)) // 28.274333882308138 }
fun 함수 이름(함수에서 사용할 파라미터) : return 값{ 함수가 할 내용 }
자바 메서드 파라미터는 디폴트가 가변이므로 함수 내부에서 변경하지 못하게 하려면 final을 지정해 불변 값으로 바꿔야 했다. 하지만 코틀린 함수의 파라미터는 무조건 불변이다.
fun increment(a: Int): Int{ return a++ // Val cannot be reassigned }
그리고 파라미터 압에 val이나 var를 표시할 수 없다는 점에 유의하라. 이렇게 강제하는 이유는 파라미터에 대입하는 중에 실수할 가능성이 높을 뿐아니라 파라미터를 불변 값으로 강제하는 편이 더 깔끔하고 이해하기 편한 코드를 만들어내기 때문이다.
코틀린 함수는 return 값을 지정해야한다. 지정되어 있지 않다면 Unit이 생략되어 있다는 의미다. (자바의 void랑 같다.)
call-by-value
코틀린은 값에 의한 호출 의미론을 사용한다. 이 말은 파라미터 값에 호출하는 쪽의 인자를 복사한다는 뜻이다. 특히 호출 인자를 전달한 변수를 변경해도 호출된 함수 내부의 파라미터 값에는 영향이 없다는 뜻이다. 하지만 파라미터가 참조라면 호출한 쪽의 데이터는 그대로 남아있고 이 데이터에 대한 참조만 복사된다. 따라서 파라미터 자체는 함수 내부에서 바뀔 쉬 없지만, 일반적으로 파라미터가 가르키는 데이터는 바뀔 수 있다.
즉 배열 같이 참조하는 데이터를 넘겨주면 함수 내부에서 변경이 외부까지 적용되지만, Int 같은 값을 나타내는 파라미터는 함수 내부에서 변경해도 외부에서는 안바뀐다는 것이다.
Call by Reference 개념 찾아보기
식이 본문 (experssion-body)인 함수
어떤 함수가 단일 식으로만 구현될 수 있다면 return 키워드와 블록을 만드는 중괄호({})를 생략하고 다음과 같은 형태로 함수를 작성해도 된다. (반환 타입 생략 가능)
fun circleArea(radius: Double) : Double = PI * radius * radius fun circleArea2(radius: Double) = PI * radius * radius
식이 본문인 함수는 간단하지만 조심스럽게 사용해야 한다. 복잡하게 표현된 식이 본문인 함수는 블록구문을 사용해 가독성을 높여주는 편이 더 낫다. (return을 추가하면 컴파일 오류 발생!!!)
fun circleArea3(radius: Double) = { PI * radius * radius }
3.1.2 위치 기반 인자와 이름 붙은 인자
기본적으로 함수 호출 인자는 순서대로 파라미터에 전달된다. 이런 방식을 위치 기만 인자(positional argument)라고 한다.
fun rectangleArea(width: Double, height: Double): Double { return width * height } println("Rectangle area: ${rectangleArea(10.0,10.0)}") // Rectangle area: 100.0
코틀린은 이름 붙은 인자(named argument)라고 불리는 방식도 제공한다.
rectangleArea(width = 10.0, height = 11.0) rectangleArea(height = 10.0, width = 11.0)
코틀린 1.4 이전에는 이름 붙은 인자를 쓰기 시작하면 그 이후의 모든 인자에 이름을 붙여야 했다. 1.4부터는 이름 붙은 인자를 중간에 섞어 쓸 수도 있다. (아래는 원본 문자열의 내용은 바뀌지 않는다.)
fun swap(s: String, from:Int, to:Int): String{ val chars = s.toCharArray() //배열 원소 교환하기 val tmp = chars[from] chars[from] = chars[to] chars[to] = tmp return chars.concatToString() }
println(swap("Hello", from=1, to=3)) // Hlleo
3.1.3 오버로딩과 디폴트 값
자바 메서드와 마찬가지로 코틀린 함수도 오버로딩을 할 수 있다. 즉, 이름이 같은 함수(parameter가 다른)를 여럿 작성할 수 있다.
fun readInt() = readln().toInt() fun readInt(radix: Int) = readln().toInt(radix)
코틀린에서는 경우에 따라 함수 오버로딩을 쓰지 않아도 된다. 더 우아한 해법인 디폴트 파라미터가 있기 때문이다. 파라미터 뒤에 변수 초기화식을 추가하면 원하는 파라미터에 디폴트 값을 제공할 수 있다.
fun readInt(radix: Int = 10) = readLine()!!.toInt(radix)
val decimalInt = readInt() val decimalInt2 = readInt(10)
3.1.4 vararg
fun printSorted(vararg items: Int){ items.sort() println(items.contentToString()) }
printSorted(6,2,10,1) // [1, 2, 6, 10]
스프레드(spread) 연산자인 *를 사용하면 배열을 가변 인자 대신 넘길 수 있다.
val numbers = intArrayOf(6,2,10,1) printSorted(*numbers)
하지만 이때 얕은 복사가 이뤄진다. 즉, 배열 내부에 참조가 들어가 있는 경우에는 참조가 복사되기 때문에 참조가 가르키는 데이터가 호출하는 쪽과 함수 내부 배열에서 공유된다.
printSorted(6, 1, *intArrayOf(3, 8), 2) //6, 1, 3, 8, 2 순서로 배열이 전달
둘 이상의 vararg 파라미터로 선언은 금지. 그러나 vararg 파라미터에 콤마로 분리한 여러 인자와 스프레드를 섞어 전달하는건 가능
3.1.5 함수의 영역과 가시성
코틀린 함수는 정의된 위치에 따라 세가지로 구분할 수 있다.
- 파일에 직접 선언된 최상위 함수
- 어떤 타입 내부에 선언된 맴버 함수
- 다른 함수 안에 선언된 지역 함수
main()과 같은 최상위 함수는 public 함수다. 즉, 프로젝트 어디에서나 쓰일 수 있다.
최상위 함수 정의 앞에 private나 internal 이라는 키워드를 붙일 수 있다. 이런 키워드를 가시성 변경자(visibility modifier)라고 부른다.
private으로 함수를 정의하면 함수가 정의된 파일 안에서만 해당 함수를 사용할 수 있다.
internal 변경자는 함수가 적용된 모듈 내부에서만 함수 의 사용이 가능
public은 디폴트로 따로 적어주지 않는다면 public이기 때문에 생략
3.2 패키지와 임포트
생략...
3.3 조건문
3.3.1 if 문으로 선택하기
(자바랑 비슷해서 일부 생략)
자바와 코틀린의 차이점은 if를 식으로 사용할 수 있다는 것이다.
fun max(a: Int, b: Int) = if(a > b) a else b
한쪽만 블록이 있을 수도 있다. 단, if else 둘다 있어야 한다.
val result = if(i > 0){ println("i is bigger than 0") }else println("i is smaller than 0")
코틀린은 자바가 가지고 있는 3항 연산자 (조건 ? A : B) 가 없다. 이 부분이 그것을 상쇄해준다.
3.3.2 범위, 진행, 연산
코틀린은 순서가 정해진 값 사이의 수열(interval)을 표현하는 몇가지 타입을 제공한다. 코틀린에서는 이런 타입을 범위(range)라고 부름
범위를 만드는 가장 간단한 방법은 .. 연산자를 사용하는 것이다.
val chars = 'a'..'z' val twoDigits = 10.. 99
'코틀린 공부 > 코틀린' 카테고리의 다른 글
[코틀린 완벽 가이드] 3장 함수 정의하기 (3.5 예외 처리) (0) 2023.12.29 [코틀린 완벽 가이드] 3장 함수 정의하기 (3.3 조건문와 3.4 루프) (0) 2023.12.29 [코틀린 완벽 가이드] 2장 코틀린 언어 기초 (2.3 - 2.4) (0) 2023.12.27 [코틀린 완벽 가이드] 2장 코틀린 언어 기초 (2.1 - 2.2) (1) 2023.12.27 [코틀린 완벽 가이드] 1장 강력하고 실용적인 코틀린 (1) 2023.12.27