데이터 클래스
data 키워드로 선언
자주 사용하는 데이터를 객체로 묶어줌. VO(value-object) 클래스를 편리하게 이용할 수 있게 해줌.
equals() 함수
객체의 데이터를 비교함
VO 클래스는 데이터를 주요하게 다루므로 데이터가 같은지 자주 비교함
❗️'객체가 같은지'가 아니라 객체의 '데이터가 같은지' 를 비교함❗️
// 데이터 클래스 선언 예시
class NonDataClass(val name: String, val email: String, val age: Int) // 일반 클래스
data class DataClass(val name: String, val email: String, val age: Int) // 데이터 클래스
// 두 클래스의 주 생성자는 매개변수 구성이 같음
// 데이터 클래스 객체 생성
fun main() {
val non1 = NonDataClass("kkang", "a@a.com", 10)
val non2 = NonDataClass("kkang", "a@a.com", 10)
val data1 = DataClass("kkang", "a@a.com", 10)
val data2 = DataClass("kkang", "a@a.com", 10)
}
// 객체의 데이터를 비교하는 equals 함수
println("non data class eqals : ${non1.equals(non2)}")
// equals()함수로 클래스의 객체를 비교하면 '객체 자체'를 비교함
println("data class equals : ${data1.equals(data2)}")
// " 데이터 클래스의 객체를 비교하면 객체 자체가 아닌 '객체의 데이터'를 비교함
실행결과:
non data class equals : false
data equals : true
데이터 클래스는 주로 주 생성자에 val, var 키워드로 매개변수를 선언해 클래스의 멤버변수로 활용하는 것이 일반적.
또한, 객체의 데이터를 비교할 때 이용하는 equals() 함수는 주 생성자에 선언한 멤버 변수의 데이터만 비교 대상으로 삼음.
// 데이터 클래스의 equals() 함수
data class DataClass(val name: String, val email: String, val age: Int) {
// 매개변수 세개인 데이터 클래스 선언
lateinit var address: String // 늦은 초기화('03 코틀린 시작하기' 포스팅 복습)
constructor(name: String, email: String, age: Int, address: String):
this(name, email, age) { // 보조생성자 선언하면서 주 생성자 함께 호출함(필수임)
this.address = address // 클래스 멤버인 this.address에 보조생성자의 매개변수인 address의 변숫값을 대입함
}
}
fun main() {
val obj1 = DataClass("kkang", "a@a.com", 10, "seoul") // 객체생성
val obj2 = DataClass("kkang", "a@a.com", 10, "busan")
println("obj1.equals(obj2) : ${obj1.equals(obj2)}") // 두 객체의 값이 같은지 비교 위해 equals() 함수 사용
}
실행결과:
obj1.equals(obj2) : true
늦은 초기화 복습 :
lateinit 규칙2가지
:var 키워드로 선언한 변수에만 사용 가능
:Int, Long, Short, Double, Float, Boolean, Byte 타입에 사용 불가(String은 사용가능)
위의 두 객체는 일부 멤버 변숫값은 다르지만, 주 생성자에 선언한 멤버 변숫값이 같아서 true 뜸!
즉, 데이터 클래스의 equals()함수는 주 생성자의 멤버 변수가 같은지만 판단한다.
toString() 함수
객체의 데이터를 반환함
일반 클래스와 데이터 클래스에서 반환값이 다름
// 데이터 클래스와 toString() 함수
fun main() {
class NonDataClass(val name: String, val email: String, val age: Int) // 일반 클래스 선언
data class Data(val name: String, val email: String, val age: Int) // 데이터 클래스 선언
val non = NonDataClass("kkang", "a@a.com", 10) // 일반 클래스 객체 생성
val data = DataClass("kkang", "a@a.com", 10) // 데이터 클래스 객체 생성
println("non data class toString : ${non.toString()}") // 일반 클래스 toString() 함수 적용
println("data class toString : ${data.toString()}") // 데이터 클래스 toString() 함수 적용
}
실행결과:
non data class toString : com.example.test4.ch2.Test2Kt.$miain$NonDataClass@61bbe9ba
data class toString : DataClass(name=kkang, email=a@a.com, age=10)
일반클래스에서의 toString() 함수 출력값은 no 의미.
데이터클래스에서는 '객체가 포함하는 멤버 변수의 데이터를 출력'함➡️ 객체의 데이터 확인할 때 유용
❗️역시 또 주 생성자의 매개변수에 선언된 데이터만 출력 대상!❗️
오브젝트 클래스
코틀린에서 주로 익명 클래스(anonymous class)를 만들 목적으로 사용됨.
익명 클래스는 말그대로 이름이 없으므로 클래스를 선언하면서 동시에 객체를 생성해야함. 그렇지 않으면 이후에 객체를 생성할 방법이 없음!🫢
// 오브젝트 클래스 사용 예
val obj = object { // 그냥 object라는 키워드 사용. 바로 변수 할당해서 객체 생성해야함~
var data = 10 // 변수명 뒤에 뒤에 이어서 바로 클래스 본문 써주기~
fun some() {
println("data : $data")
}
}
fun main() {
obj.data = 20 // 오류! 허걱~
obj.some() // 오류! 허걱~~~
}
❓왜 객체로 클래스에 선언한 멤버에 접근 할 수 없을까?
✅클래스의 타입을 명시하지 않았기 때문!! 타입 명시 안하면 'Any'로 취급됨. 근데 Any타입 객체에는 data, some() 이라는 멤버가 없어서 오류가 발생함.🤔
😯그래서 object { } 형태로 익명클래스를 선언할 수는 있지만 보통은 타입까지 함께 입력해서 선언함.(오브젝트 클래스의 타입은 object 뒤에 콜론(:)입력하고 뒤에 클래스의 상위 또는 인터페이스 입력)
// 타입을 지정한 오브젝트 클래스
open class Super { // open 키워드 사용해서 클래스 정의
open var data = 10 // 멤버 변수도 open
open fun some() {
println("I am super some() : $data")
}
}
val obj = object: Super() { // Super클래스 상속받은 익명클래스 선언과 익명객체 생성
override var data = 20 // 멤버변수 재정의(오버라이딩)
override fun some() {
println("I am object some() : $data")
}
}
fun main() {
obj.data = 30 // 성공~
obj.some() //성공~
}
obj객체로 Super 클래스에 선언된 멤버에 접근할 수 있게 됨~~
컴패니언 클래스
멤버 변수나 함수를 클래스 이름으로 접근하고자 할 때 사용함
일반적으로 클래스의 멤버는 객체를 생성해서 접근해야 하는데, 컴패니언 클래스는 객체를 생성하지 않고서도 클래스 이름으로 특정 멤버를 이용할 수 있게 함!
// 일반 클래스의 멤버 접근
class MyClass { // 매개변수 없는 클래스 생성, 생성자도 생략했음
var data = 10
fun some() {
println(data)
}
}
fun main() {
val obj = MyClass() // 객체 생성
obj.data = 20 // 객체명으로 멤버변수에 접근
obj.some() // 객체명으로 멤버함수에 접근
MyClass.data = 20 // 클래스이름으로 접근 ➡️ 오류!!
MyClass.some() // 오류!
}
일반클래스에서는 클래스이름으로 멤버변수에 접근하면 오류남(객체명으로는 접근 가능)
// 컴패니언 클래스의 멤버 접근
class MyClass { // 매개변수 없고 생성자도 생략한, 일반 클래스 선언
companion object { // companion (+object) 키워드 사용해서 클래스이름으로 멤버에 접근할 수 있게 함
var data = 10
fun some() {
println(data)
}
}
}
fun main() {
MyClass.data = 20 // 성공
MyClass.some() // 성공
}
클래스 내부에 companion object { } 형태로 선언하면 이 클래스를 감싸는 클래스 이름으로 멤버에 접근할 수 있다~
'깡샘 코틀린' 카테고리의 다른 글
05-2 널 안정성 (0) | 2023.06.15 |
---|---|
05-1 람다 함수와 고차 함수 (0) | 2023.06.15 |
04-2 클래스를 재사용하는 상속 (0) | 2023.06.14 |
04-1 클래스와 생성자 (0) | 2023.06.13 |
03 코틀린 시작하기 (0) | 2023.06.06 |