Do it! 코틀린 프로그래밍 [둘째마당, 객체 지향 프로그래밍] 학습
자원의 낭비를 막고 오로지 데이터 저장에 초점을 맞추기 위해 코틀린에서 특별히 고안된 클래스
📌 DTO(Data Transfer Object)
📌 데이터 클래스에서 내부적으로 자동 생성되는 메서드
equals()
와 키 사용을 위한 hashCode()
toString()
copy()
component1()
, component2()
등📌 데이터 클래스 선언과 조건
data class Customer(var name: String, var email: String)
abstract
open
sealed
inner
키워드 사용 불가📌 객체 디스트럭처링
data class Customer(var name: String, var email: String) { }
fun main(){
val customer1 = Customer("Sean", "sean@mail.com")
val (name, email) = customer1
// name 프로퍼티가 필요 없는 경우
val (_, email) = customer1
// 개별적으로 프로퍼티를 가져오기
val name = customer1.component1()
val email = customer1.component2()
}
-> customer1 객체의 프로퍼티 값 2개를 각각 name과 email로 선언된 변수로 가져옴
-> 가져올 필요가 없는 프로퍼티는 언더스코어( _ )를 사용해 제외
-> 개별적으로 프로퍼티를 가져오기 위해 componentN()
메서드를 사용
⬇️ 람다식을 사용해 디스트럭처링된 변수 출력하기
val myLamda = {
(nameLa, emailLa): Customer ->
println(nameLa)
println(emailLa)
}
myLambda(customer1)
// 자바의 멤버(이너) 클래스
class A {
class B { /* 외부 클래스 A의 필드에 접근 가능 */ }
}
// 코틀린의 이너 클래스
class A {
inner class B { /* inner 키워드 필요, 외부 클래스 A의 필드에 접근 가능 */}
}
// 자바의 정적 클래스
class A {
static class B { /* 정적 클래스를 위해 static 키워드 사용 */ }
}
// 정접 클래스러처럼 사용한 코틀린의 중첩 클래스
class A {
class B { /* 아무 키워드가 없으면 중첩 클래스 */
/* 외부 클래스 A의 프로퍼티, 메서드에 접근할 수 없음 */
}
}
📌 중첩 클래스 (Nested Class)
class Outer {
val ov = 5
class Nested {
fun greeting() { }
/* 외부 프로퍼티 ov에는 접근 불가 */
}
fun outside() {
val msg = Nested().greeting() // 객체 생성 없이 중첩 클래스의 메서드 접근
}
}
fun main() {
// static 처럼 객체 생성 없이 사용
val output = Outer.Nested().greeting()
val Outer.ov // !오류! 외부 클래스는 객체 생성없이 접근 불가
}
⬇️ 중첩 클래스에서 외부 프로퍼티에 접근하기
class Outer {
class Nested {
fun accessOuter() {
println(country) // 컴패티언 객체에 접근
}
}
companion object { const val country = "Korea" }
}
-> 컴패니언 객체는 객체 생성 없이 고정적인 메모리를 가지기 때문에 Nested클래스에서 Outer클래스의 프로퍼티인 country에 접근 가능
📌 이너 클래스 (Inner Class)
inner
키워드 사용class Outer {
private val ov = 5
inner class Inner {
// 바깥 클래스의 private 프로퍼티인 ov에 접근
fun getOV() = println(ov)
}
}
📌 지역 클래스 (Local Class)
class Outer {
private val ov = 5
fun localClassFunc() {
class InnerClass(val iv: String) { // 지역 클래스 선언
fun innerIV() = "$iv access $ov" // 외부 클래스 프로퍼티에 접근 가능
}
val innerClass = InnerClass("inner class")
println(innerClass.iv)
} // PowerOn 블록 끝
}
📌 익명 객체 (Anonymous Object)
interface anonymousObject {
fun ao()
}
class Outer {
// 익명 객체를 사용해 anonymousObject의 ao()를 구현
val anonymousObject = object: anonymousObject {
override fun ao() { /* 구현부 */ }
}
fun test() {
anonymousObject.ao() // 익명 객체의 메서드 사용
}
}
-> 메서드가 호출될 때마다 일회성 객체의 인스턴스가 만들어짐
📌 실드 클래스 (Sealed class)
sealed class Result {
open class Success(val message: String): Result()
class Error(val code: Int, val messeage: String): Result()
}
class Status: Result() // 실드 클래스 상속
class Inside: Result.Success("Status") // Result의 내부 클래스 Success 상속
📌 열거형 클래스 (Enum Class)
enum class 클래스 이름 [(생성자)] {
상수1[(값)], 상수2[(값)], 상수3[(값)], ...
[; 프로퍼티 혹은 메서드]
}
⬇️ 열거형 클래스 예시
enum class DayOfWeek(val num: Int) {
MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4),
FRIDAY(5), SATURDAY(6), SUNDAY(7);
// 세미콜론으로 끝을 알리고
// 메서드를 포함할 수 있음
fun day() { }
}
val day = DayOfWeek.SATURDAY
when(day.num) {
1,2,3,4,5 -> println("Weekday")
6,7 -> println("Weekend")
}
-> 필요한 경우 열거형 클래스 내부에 세미콜론(;)을 이용해 메서드를 포함할 수 있음