9. 데이타클래스, 중첩클래스 (Data, Nested classes)
1. Data 클래스
1-1. 기본
- 용도 : 데이터는 보유하지만 아무것도 하지 않는 클래스
- 코틀린에서는 data class 를 제공해준다.
data class User(val name: String, val age: Int)
1-2. 자동생성 메서드
기본 생성자에서 선언된 속성을 통해 컴파일러가 자동적으로 생성해준다
- equals()
- hashCode()
- copy()
- toString()
- componentN() funtions
- 명시적으로 정의하는 경우에는 자동으로 생성해 주지 않는다.
1-3. 의미있는 생성 조건
- 의미있는 Data 클래스의 조건
- 기본생성자에 1개 이상의 파라미터
- 기본생성자의 파라미터가 var, val로 선언
- Data클래스는 abstract, open, sealed, inner가 안됨
- Data 클래스 interface구현 기능 (1.1버전 이후)
- Sealed class 상속가능 (1.1버전 이후)
fun foo() { val obj = User("BAE",32) println(obj) // User(name=BAE, age=32)로 출력된다. 주소값이 출력되는게 아닌 toString() }
toString() 그 외에도 실제 디컴파일해보면 여러가지 메서드들이 생성되있다.
1-4. 기본 특징 및 설정
- 기본값 설정
- JVM에서 파라미터 없는 생성자가 필요한 경우 모든 프로퍼티에 기본 값을 설정해 주면 된다.
data class User(var name: String = "", var age:Int = 0) // 기본값 설정해주면 된다. val obj = User(); //파리머터없는 생성자도 가능. val obj2 = User("TEST") // name이 TEST로 변경되서 출력된다. (타입에 따라 추론가능하니까) val obj3 = User("BAE", 32) // 두가지 모두 설정 val obj4 = User(age=444) // age만 바꿀경우, 지정하여서 출력도 가능
- 바디에도 변수를 만들 수 있다. (단 컴파일러가 만들어주는 메서드는 적용되지 않는다.)
data class User(var name: String, var age:Int) {
var other1: Int = 1
}
/*
위처럼, 바디에 변수를 넣더라도, 자동으로 생성되는 메서드들은 생성되지 않는다.
*/
fun foo() {
val obj = User("BAE",32)
println(obj) // User(name=BAE, age=32)로 출력된다. 바디에 변수를 넣더라도 적용안됨.!
}
1-5. 복사
- 객쳉릐 기존 값들을 유지하고, 일부 값만 고쳐서 새로운 객체를 만들고 싶은 경우
- 데이타 클래스에 컴파일러가 copy를 만들어 주기 때문에 바로 copy를 호출해서 사용하면 됨
val bae = User(name= "bae", age = 32)
val oldBae = bae.copy(age = 80)
// 위처럼 할시, 나이만 80살로 바뀐 oldBae객체가 생성 된다.
1-6. Destrcturing Declarations
- data 클래스는 Destrcturing Declarations 사용 가능.
- 컴파일러가 componentN 함수를 자동으로 만들어주기 때문.
val bae = User("BAE", 32)
val (name, age) = bae //val (name, age) = User("BAE", 32)
println("$name, $age")
//기존의 JAVA 형태의 경우라면..
val bae = User("BAE", 32)
val name = bae.name
val age = bae.age
println("$name, $age")
// 이렇게 하나씩 꺼내와야되지만 코틀린은 변수를 동시에 꺼내올 수 있다.
// 데이터 클래스가 컴파일러가 componentN 함수를 자동으로 만들어주기 때문.
1-7. data 클래스 없이 간단한 값 뽑기, Pair, Triple
val obj = Pair("BAE", 32) // val obj = Pair<String, Int>("BAE", 32)
println(obj) // (BAE, 32) 로 출력된다.
// 기본 data 클래스 방식 방식
val obj2 = User("BAE", 32)
println(obj2) // User(name=BAE, age=35) 로 출력된다
2가지 ⇒ Pair
3가지 ⇒ Triple
다만, 코틀린에서는 data클래스 방식대로 하는것이 좋다고 권고하고있다.
2. 중첩,내부 클래스 (Nested Classes, Inner Class)
2-1. 중첩클래스 (Nested Classes)
- 클래스는 다른 클래스에 중첩될 수 있다.
- 중첩만 되어있을뿐, 내부에서 외부의 멤버에 접근 할 수 없다.
class Outer {
private val bar: Int = 1
class Nested {
fun foo() = 2
//중첩만 되어있을뿐, 내부에서 외부의 bar변수에 접근 할 수 없다.
}
}
val test = Outer.Nested().foo() // 2
2-2. 내부클래스 (Inner Class)
- 클래스에 inner를 표기하면 바깥쪽 클래스의 멤버에 접근할 수 있다.
class Outer {
private val bar: Int = 1
inner Class Inner {
fun foo() = bar
}
}
val test = Outer().Inner().foo() // 1 ( Outer() 로 호출하여야 함 )