참조
코틀린 특성
JAVA와 비슷한점
- OOP 등 4가지 기본 원칙
JAVA와 다른점
getter, setter
- 클래스 속성에는 기본값으로 getter, setter가 기본값(public)하게 붙는다
- var의 경우 getter, setter
- val의 경우 getter
- 하위방식으로 필드값에 대한 getter, setter가 설정가능하다.
1 | var speakerVolume = 2 |
기본생성자, 보조생성자
기본생성자는 생략가능(매개변수화된 생성자 정의)(=constructor arguments)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class SmartDevice constructor() {
...
}
//생략시
class SmartDevice (val name: String, val category: String) {
var deviceStatus = "online"
fun turnOn() {
println("Smart device is turned on.")
}
fun turnOff() {
println("Smart device is turned off.")
}
}보조생성자는 기본생성자 매개변수와 다를때, 정의가능
1
2
3
4
5
6
7
8
9
10
11
12
13class SmartDevice(val name: String, val category: String) {
var deviceStatus = "online"
//해당 부분은 statusCode 매개변수를 받아서 보조생성자로 객체생성, this=기본생성자를 뜻함
constructor(name: String, category: String, statusCode: Int) : this(name, category) {
deviceStatus = when (statusCode) {
0 -> "offline"
1 -> "online"
else -> "unknown"
}
}
...
}
기본적으로 닫혀있는 상속
코틀린은 기본적으로 클래스가
final
이다. 따라서 다른 클래스에서 상속이 불가능하다.따라서 상속을 허용하려면
open
변경자가 붙어야한다.또한 오버라이드를 허용하고 싶은 메서드나 프로퍼티의 앞에도
open
필요하다.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22open class Car {
// 이 메서드는 하위 클래스에서 override 불가능
fun getNumberOfTires(): Int {
return 4
}
// 하위 클래스에서 override 가능
open fun hasSunRoof() :Boolean {
return false
}
}
// open 클래스는 상속이 가능하다!
class Benz() : Car() {
// getNumberOfTires 메서드는 override 불가능
// hasSunRoof 메서드는 open변경자가 붙어서 override 가능
override fun hasSunRoof(): Boolean {
return true
}
}abstract
클래스는abstract
메서드,open
를 활용할수있습니다.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22abstract class Animal {
// 추상 메서드는 반드시 override 해야 함
abstract fun bark()
// 이 메서드는 하위 클래스에서 선택적으로 override 할 수 있다. (하거나 안하거나 자유)
open fun running() {
println("animal running!")
}
}
class Dog() : Animal() {
override fun bark() {
println("멍멍")
}
// 이 메서드는 override 하거나 하지 않거나 자유.
override fun running() {
println("dog's running!")
}
}
공개 상태 수정자[public(=default), internal, protected, private]
자바와 다른개념
변경자 클래스 멤버 최상위 선언 public(기본값) 모든 곳에서 볼 수 있다 모든 곳에서 볼 수 있다 internal 같은 모듈 안에서만 볼 수 있다 같은 모듈 안에서만 볼 수 있다 protected 하위 클래스 안에서만 볼 수 있다 (최상위 선언에 적용할 수 없음) private 같은 클래스 안에서만 볼 수 있다 같은 파일 안에서만 볼 수 있다
data class
자바에서 대게
equals
,hashCode
,toString
을 오버라이드 해야하는 경우가 많았습니다. 코틀린은 이런 불편함을 줄이기 위해data
라는 변경자를 클래스 앞에 붙이면 필요한 메서드를 컴파일러가 자동으로 만들어줍니다.data
변경자가 붙은 클래스를 데이터 클래스라 부릅니다.데이터 클래스의 프로퍼티가 꼭
val
일 필요는 없지만, 데이터 클래스의 모든 프로퍼티를 읽기 전용으로 만들어서 데이터 클래스를 불변(immutable) 클래스로 만들라고 권장합니다.데이터 클래스 인스턴스를 불변 객체로 더 쉽게 활용할 수 있게 코틀린 컴파일러는
copy
메서드를 제공합니다.copy
메서드는 객체를 복사하면서 일부 프로퍼티를 바꿀 수 있게 해줍니다. 복사본은 원본과 다른 생명주기를 가지며, 복사를 하면서 일부 프로퍼티 값을 바꾸거나 복사본을 제거해도 프로그램에서 원본을 참조하는 다른 부분에 전혀 영향을 끼치지 않습니다.(p3, p4참조)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20data class Person(val name:String, val age:Int)
fun main() {
val p1 = Person("conatuseus",30)
val p2 = Person("conatuseus",30)
// == 은 동등성 검사
println(p1==p2)
// === 은 같은 인스턴스인지 검사(동일성 확인)
println(p1===p2)
println(p1.toString())
val p3 = p1.copy() //clone처럼 copy가능
val p4 = p1.copy(name = "newName",age = 20)
}
//출력
// true, false, Person(name=conatuseus, age=30)
코틀린 기본 문법
1 |
|
Advanced
속성 위임 정의(by)
구현을 위임할 수 있는 클래스를 구현하려면 먼저 인터페이스를 잘 알아야 합니다. 인터페이스는 구현하는 클래스가 준수해야 하는 계약으로서, 작업을 하는 방법이 아닌 해야 할 작업에 중점을 둡니다. 간단히 말해 인터페이스는 추상화하는 데 유용합니다.
(작성중)
엘비스 연산자
?:
(엘비스 연산자)의 동작 방식:왼쪽의 값이
null
이 아니면 그 값을 반환하고,만약 왼쪽 값이
null
이면 오른쪽의 값을 반환하거나, 오른쪽에 특정 연산(예: 예외 던지기)을 수행합니다.
1 | val value: String? = null |
인라인 (inline)
인라인 함수(inline function)는 함수 호출 오버헤드를 줄이기 위한 최적화 기법입니다. 함수가 호출될 때, 보통은 호출된 함수로 제어가 이동하고, 함수가 끝난 후 다시 호출 지점으로 돌아가는 과정이 필요합니다. 이 과정은 특히 작은 함수일 때도 오버헤드가 발생할 수 있습니다.
인라인 함수는 이 문제를 해결하기 위해 함수 호출을 제거하고, 함수의 본문을 호출한 곳에 직접 복사하는 방식으로 처리합니다. 이를 통해 성능을 최적화할 수 있습니다.
Kotlin에서는 inline
키워드를 사용하여 인라인 함수를 정의할 수 있습니다. 인라인 함수는 특히 람다를 인자로 받는 고차 함수에서 성능 최적화 효과가 큽니다.
인라인 함수의 특징
- 함수 호출 오버헤드 제거: 호출된 함수로 제어가 이동하지 않고, 코드가 호출된 곳에 복사되므로 성능이 향상됩니다.
- 람다식의 성능 최적화: 인라인 함수에 전달되는 람다식은 객체로 변환되지 않고 인라인 처리됩니다.
- 재귀 함수는 인라인 불가능: 재귀 함수는 반복적으로 자기 자신을 호출하므로 인라인으로 변환할 수 없습니다.
예시
1 | inline fun <reified T, ID> CrudRepository<T, ID>.findByIdOrThrow(id: ID, message: String = "해당 ID의 데이터가 존재하지 않습니다."): T = findByIdOrNull(id) ?: throw NoSuchElementException(message) |
1 | inline fun runIfTrue(condition: Boolean, block: () -> Unit) { |
companion object
- java static 객체라고 생각하면됨.
- 클래스에 정의된 static class
1 | class SignUtils(private val signService: SignService) { |
- 호출시 다음과같이 가능
1 | SignUtils.numberOperation("실행쌉가능", 1,2,{x,y->x*y+x}) |