- QueryDSL
- arc browser
- Spring
- java_to_kotlin
- 라즈베리파이 클러스터
- 무료 아이콘 폰트
- 디자인패턴
- restcontroller
- 리믹스아이콘
- java
- restdocs
- spring cloud contract
- remix icon
- springboot
- oraclejdk
- OneToMany
- Openjdk
- 폰트어썸
- 라즈베리파이
- 도커
- openapispec
- 옵저버패턴
- with jdk
- Spring Cloud
- Observer Pattern
- EntityGraph
- kotlin
- fontawesome
- Docker
- 전략패턴
- Today
- Total
< Dev-Kidult />
Java to Kotlin - 3. 클래스와 함수 본문
클래스
Constructor
자바에서는 클래스명과 동일한이름의 함수로 생성자를 지정할 수 있다.
class A {
private String name;
private String email;
A() {}
A(String name, String email) {
this.name = name;
this.email = email;
}
}
var a = new A();
코틀린은 아래와 같다.
class A(var name: String?, var email: String?) : B() {
init {
// ...
}
constructor(name: String?) : this(name, null)
constructor() : this(null)
}
var a = A()
- primary constructor class A(var name: String?, var email: String?)
- class A @Inject public constructor(var name: String?, var email: String?)
- 기본 생성자에도 constructor 키워드가 있으나 생략 할 수 있다.
- 가시접근자 혹은 어노테이션을 함께 쓸때는 constructor 키워드를 같이 써야 한다.
- init block init {...}
- init 블록은 클래스안에 하나 또는 여러개가 선언 될 수 있으며, 객체가 생성될 때 생성자보다 우선하여 호출된다.
- secondary constructor constructor() : this(null, null), constructor() : this(null)
- 객체를 선언할 때 자바와는 다르게 new키워드가 빠진다.
Inheritance
open class B(x: Int?) {
constructor(): this(null)
open val y: Int = 5
}
class A(x: Int?): B(x) {
constructor(): super()
override final val y: Int = 6
}
코틀린에서의 Class는 기본적으로 final Class이다. 확장을 해주려면 open 키워드를 붙여줘야 한다.
property 또한 오버라이드 하려면 open 키워드를 붙여줘야 한다.
그리고 오버라이드 된 필드 자체도 열려있으므로 하위객체에서 오버라이드를 막고 싶다면 final을 적도록 하자.
Static , Compaion Object
public Class Person {
public static final int MAX_AGE = 50;
}
Person.MAX_AGE
class Person {
companion object {
const val MAX_AGE = 50
}
}
Person.MAX_AGE
하지만 꼭 그래야만 하는건 아니다. java와 달리 class가 1급객체인 언어라 아니라서 class로 감싸지 않아도 쓸 수 있다. (상황에 따라 다르지만 전 이쪽을 선호하는편)
물론 함수도 위와 같다.
Delegation
코틀린은 기본적으로 by키워드를 통해 위임패턴을 지원한다.
interface Base {
fun printMessage()
fun printMessageLine()
}
class BaseImpl(val x: Int) : Base {
override fun printMessage() { print(x) }
override fun printMessageLine() { println(x) }
}
class Derived(b: Base) : Base by b {
override fun printMessage() { print("abc") }
}
fun main() {
val b = BaseImpl(10)
Derived(b).printMessage()
Derived(b).printMessageLine()
}
기본적으로 BaseImpl에서 오버라이드 된 함수를 실행시키지만 추가로 Derived에 오버라이드가 되어있다면 해당값 또는 함수를 참조한다.
Delegate Properties
코틀린에는 클래스 말고도 프로퍼티에도 위임을 할 수 있는 기능이 있다.
구현이 되어있는것도 있고, 구현도 할 수 있다.
class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, thank you for delegating '${property.name}' to me!"
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$value has been assigned to '${property.name}' in $thisRef.")
}
}
class Example {
var p: String by Delegate()
}
val e = Example()
println(e.p)
//Example@~~~~~, thank you for delegating 'p' to me!
e.p = "NEW"
//NEW has been assigned to 'p' in Example@~~~~~.
deletgate로 쓰려면 위처럼 operator로 구현된 getValue, setValue 함수가 있어야 한다.
getValue 함수는 가져올 때 그리고 serValue는 해당 프로퍼티에 값을 넣을때 동작하게 된다.
lazy properties
val lazyValue: String by lazy {
println("computed!")
"Hello"
}
fun main() {
println(lazyValue)
println(lazyValue)
}
//computed!
//Hello
//Hello
Observable properties
class User {
var name: String by Delegates.observable("<no name>") {
prop, old, new ->
println("$old -> $new")
}
}
fun main() {
val user = User()
user.name = "first"
user.name = "second"
}
//<no name> -> first
//first -> second
Storing properties in a map
class User(val map: Map<String, Any?>) {
val name: String by map
val age: Int by map
}
val user = User(mapOf(
"name" to "John Doe",
"age" to 25
))
println(user.name) // Prints "John Doe"
println(user.age) // Prints 25
맵에도 위같이 사용 할 수 있다.
그리고 MutableMap을 사용하는경우에는 var를 사용하여서 속성을 수정하는것도 가능하다.
Type aliases
말그래도 타입을 지정할 수 있는 기능이다.
typealias NodeSet = Set<Network.Node>
typealias FileTable<K> = MutableMap<K, MutableList<File>>
typealias MyHandler = (Int, String, Any) -> Unit
typealias Predicate<T> = (T) -> Boolean
클래스뿐만 아니라 고차함수도 지정가능하다.
함수
Extensions
코틀린에서는 함수확장이 가능하다.
fun <T> MutableList<T>.swap(index1: Int, index2: Int) {
val tmp = this[index1]
this[index1] = this[index2]
this[index2] = tmp
}
val list = mutableListOf(1, 2, 3)
list.swap(0, 2)
Infix
앞서 range를 지정하는곳에서 이런 코드를 봤었을꺼다.
val range = 0 until 10 // eq 0.until(10)
val progression = 10 downTo 0 step 2 // eq 10.downTo(0).step(2)
val map = mapOf("one" to 1, "two" to 2) // eq "one".to(1)
위 코드 모두 infix 함수로 구현되어있는 함수이다.
일반적인 () 형태의 함수 호출방식이 아닌 띄어쓰기를 포함한 키워드를 통해서 함수를 호출하는 방식이다.
infix 함수를 구현하기 위해서는 아래 3가지 조건을 만족해야 한다.
- 멤버 함수 또는 확장함수여야 한다.
- 단일 매개변수여야 한다.
- 매개변수는 가변 개수의 인수를 허용하지 않아야 하며, 기본값이 없어야 한다.
//ex
infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)
operator
자바에서도 코틀린에서도 많은 연산자를 통해 사용 할 수 있는 기능들이 있다.
+a, -a, !a, a++, a--, a+b, a-b, a*b, a/b, ...
코틀린에서는 위 연산자도 오버라이딩이 가능하며, 적용범위또한 클래스등 여러범위에 사용 할 수 있다.
//ex
data class Point(val x: Int, val y: Int)
operator fun Point.unaryMinus() = Point(-x, -y)
val point = Point(10, 20)
fun main() {
println(-point) // prints "Point(x=-10, y=-20)"
}
해당되는 식 및 해당 함수는 아래와 같다.
Expression |
Func |
+a | a.unaryPlus() |
-a | a.unaryMinus() |
!a | a.not( |
a++ | a.inc() |
a-- | a.dec() |
a + b | a.plus(b) |
a - b | a.minus(b) |
a * b | a.times(b) |
a / b | a.div(b) |
a % b | a.rem(b) |
a..b | a.rangeTo(b) |
a in b | b.contains(a) |
a !in b | !b.contains(a) |
a[i] | a.get(i) |
a[i, j] | a.get(i, j) |
a[i_1, ..., i_n] | a.get(i_1, ..., i_n) |
a[i] = b | a.set(i, b) |
a[i, j] = b | a.set(i, j, b) |
a[i_1, ..., i_n] = b | a.set(i_1, ..., i_n, b) |
a() | a.invoke() |
a(i) | a.invoke(i) |
a(i, j) | a.invoke(i, j) |
a(i_1, ..., i_n) | a.invoke(i_1, ..., i_n) |
a += b | a.plusAssign(b) |
a -= b | a.minusAssign(b) |
a *= b | a.timesAssign(b) |
a /= b | a.divAssign(b) |
a %= b | a.remAssign(b) |
a == b | a?.equals(b) ?: (b === null) |
a != b | !(a?.equals(b) ?: (b === null)) |
a > b | a.compareTo(b) > 0 |
a < b | a.compareTo(b) < 0 |
a >= b | a.compareTo(b) >= 0 |
a <= b | a.compareTo(b) <= 0 |
예외적으로 주소값 자체를 비교해주는 ===, !===는 확장구현 할 수 없다.
'개발 > Back-end' 카테고리의 다른 글
Springboot API 문서 자동화 (0) | 2022.12.29 |
---|---|
Java to Kotlin - 4. 코틀린 표준 라이브러리 (0) | 2022.12.28 |
Java to Kotlin - 2. 조건문과 반복문 (0) | 2022.12.28 |
Java to Kotlin - 1. 코틀린의 타입 시스템 (0) | 2022.12.28 |
Java to kotlin - 0. kotlin? (0) | 2022.12.28 |