+ 항공대학교 김철기 교수님의 객체 지향 프로그래밍 과목 내용를 정리한 글입니다.
Kotlin 함수의 예
import kotlin.math.PI // kotlin 패키지에서 PI 상수를 가져옴
fun circleArea(radius: Double): Double { // 함수의 정의
return PI * radius * radius
}
fun main() {
print("Enter radius: ")
val radius = readLine()!!.toDouble()
println("Circle area: ${circleArea(radius)}")
}
Kotlin 함수의 특징 (1)
- 파라미터의 타입은 항상 지정해야 한다.
fun circleArea(radius: Double): Double // O
fun circleArea(radius): Double // X
- 반환값이 없는 경우만 반환값의 타입을 생략할 수 있다.
(C의 void 함수 = Kotlin의 Unit 함수)
fun prompt(name: String) {
println("*** Hello, $name! ***")
}
fun prompt(name: String): Unit { // 위 함수와 동일
println("*** Hello, $name! ***")
}
Kotlin 함수의 특징 (2)
- 파라미터의 값은 수정이 불가능하다. (파라미터는 val변수의 특성을 갖는다.)
fun foo(bar: Int): Int {
bar += 1 // Error
return bar
}
fun foo(bar: Int): Int {
val baz = bar + 1 // 새로운 변수에 할당하여 변경
return bar
}
식 하나가 본문인 함수
- 함수형 언어에서 영향을 받았다.
- 식 하나로 표현이 가능한 함수의 경우 return을 생략하고 =로 함수 선언과 본문을 연결할 수 있다.
fun circleArea(radius: Double): Double = PI * radius * radius
- 식에서 반환값의 타입이 유추가 가능한 경우 반환 타입 생략이 가능하다. (타입 추론)
fun circleArea(radius: Double): = PI * radius * radius
함수의 호출
- 함수를 호출할 때 세 가지 형태가 모두 가능하며 동일한 의미이다.
fun rectangleArea(width: Double, height: Double) = width * height
fun main() {
val w = readLine()!!.toDouble()
val h = readLine()!!.toDouble()
println(rectangleArea(w, h))
println(rectangleArea(width = w, height = h))
println(rectangleArea(height = h, width = w))
}
=> 즉, 파라미터의 이름으로 인자를 전달할 수 있다.
함수의 오버로딩
- 동일한 이름의 함수를 파라미터 타입의 변이에 따라 여러 버전으로 정의하는 프로그래밍
- 객체지향 연구자들이 주장한 개념으로 객체지향적 개념으로 분류한다.
- 다형성(polymorphism)의 일종이다. (형: 타입)
- 변수의 이름이 부족한 현상을 해결해준다.
// 두 함수를 동시에 정의 가능
fun readInt() = readLine()!!.toInt()
fun readInt(radix: Int) = readLine()!!.toInt(radix) // radix진법을 입력 받고 10진법으로 반환
fun main() {
val num1 = readInt()
val num2 = readInt(2)
println("num1: $num1, num2: $num2")
}
함수 호출 시 오버로딩 해소 규칙
1. 파라미터의 개수와 타입을 기준으로 호출할 수 있는 모든 함수를 찾는다.
2. 덜 구체적인 함수를 제외한다. 어떤 함수의 파라미터 타입이 다른 함수에 비하여 포괄적일 경우 이를 제외한다. 이 과정을 하나의 함수가 남을 때까지 반복한다.
3. 하나가 남으면 해당 함수를 호출한다. 두 개 이상이 남으면 컴파일 에러가 발생한다.
함수 오버로딩의 예
fun mul(a: Int, b: Int) = a * b
fun mul(a:Int, b: Int, c: Int) = a * b * c
fun mul(s: String, n: Int) = s.repeat(n)
fun mul(o: Any, n: Int) = Array(n) {o}
// Array(n): 길이가 n인 배열 생성
// {o}: 각 요소를 o으로 채운다.
fun main() {
println(mul(1, 2)) // 1번 함수 호출
println(mul(1L, 2)) // 4번 함수 호출
println(mul("O" as Any,3)) // 4번 함수 호출
// 문자열 "O"를 상위 개념인 Any 타입으로 생각하고 호출 수행
println(mul("O", 3)) // 3번 함수 호출
}
함수의 디폴트 파라미터
// 파라미터가 주어지지 않으면 자동으로 10을 파라미터로 갖는다.
fun readInt(radix: Int = 10) = readLine()!!.toInt(radix)
fun main() {
val decimalInt = readInt()
val decimalInt2 = readInt(10) // 위와 동일한 함수 호출이다.
println("$decimalInt, $decimalInt2")
}
함수의 가시성
1. public 함수
- 프로젝트의 어디서나 해당 함수 호출이 가능하다.
- 가시성 선언이 없는 함수는 디폴트로 public 선언된다.
fun readInt(): Int = readLine()!!.toInt()
// 디폴트 public 가시성으로 정의
2. internal 함수
- 함께 컴파일되는 모듈 안에서만 호출이 가능하다.
internal fun readInt(): Int = readLine()!!.toInt()
3. private 함수
- 같은 파일 안에서만 호출이 가능하다.
private fun readInt(): Int = readLine()!!.toInt()
함수 내 함수
- 함수를 감싸는 블록에서만 호출이 가능하다.
=> 특정 함수내에서만 사용되는 함수를 다른 곳에서는 사용하지 않음을 나타낸다는 장점이 존재한다.
- 함수 내 변수에 접근이 가능하다.
=> 인자에 전달하지 않아도 되므로 오버헤드(복잡도)가 줄어든다. (인자 수가 줄어든다.)
fun main(args: Array<String>) {
// String 배열 args 받아오기
fun swap(i: Int, j: Int): String {
val chars = args[0].toCharArray()
// String 배열 args의 첫번째 문자열을 char 배열로 변환 후 chars에 저장
val tmp = chars[i]
// i 위치의 문자를 tmp에 저장
chars[i] = chars[j]
// chars의 i번째 문자를 chars의 j번째 문자로 변경
return chars.concatToString()
// char 배열로 변경되었던 chars를 다시 String로 변경하여 반환
}
println(swap(0, args[0].lastIndex))
// swap 함수 호출
// 주어진 문자열 args의 첫번째 문자열의 첫번째 문자를 마지막 문자로 바꾼후 출력
}
'Study > Kotlin Study' 카테고리의 다른 글
| [Kotlin] 단순한 변수 이상인 프로퍼티 (0) | 2023.09.17 |
|---|---|
| [Kotlin] 널 가능성 (0) | 2023.09.12 |
| [Kotlin] 클래스 정의하기 (1) | 2023.08.28 |
| [Kotlin] 예외 처리 (0) | 2023.08.25 |
| [Kotlin] 루프 (반복문) (2) | 2023.08.24 |