Companion Object (컴패니언 객체) : 프로그램을 실행할 때 고정적으로 가지는 메모리로 객체 생성 없이 사용할 수 있다.(정적 변수?)
# Companion Object & Singleton pattern의 사용
package chap02.section1
class Person {
var id : Int = 0
var name : String = "Youngdeok"
companion object {
var language : String = "Korean"
fun work() {
println("working...")
}
}
}
fun main() {
println(Person.language) // 인스턴스를 생성하지 않고 기본값 사용
Person.language = "English" // 기본값 변경 가능
println(Person.language) // 변경된 내용 출력
Person.work()
//println(Person.name) // name은 컴패니언 객체가 아니므로 오류
}
/*
Person 클래스의 language는 객체의 생성 없이도 접근할 수 있게 되었다. 물론 work() 멤버 메서드도 객체 생성 없이 실행할 수 있다.
컴패니언 객체는 실제 객체의 싱글톤(Singleton)으로 정의된다.
Singleton : d전역 변수를 사용하지 않고 객체를 하나만 생성하도록 하여, 생성된 객체를 어디에서든지 참조할 수 있도록 하는 디자인 패턴
사용 이유 ? 객체가 서로 동일한 정보를 가질 때 하나의 메모리만 유지해 자원의 낭비를 줄일 수 있기 때문이다.
*/
# Object 선언
package chap02.section1
// (1) Object 키워드를 사용한 방식
object OCustomer {
var name : String = "Kildong"
fun greeting() = println("Hello World OCustomer")
val HOBBY = Hobby("Basketball")
init {
println("Init!")
}
}
// (2) 컴패니언 객체를 사용한 방식
class CCustomer {
companion object {
const val HELLO = "hello" // 상수 표현
var name = "Joosol"
@JvmField val HOBBY = Hobby("Football")
@JvmStatic fun greeting() = println("Hello world CCustomer")
}
}
class Hobby(val name : String)
fun main() {
OCustomer.greeting() // 객체의 접근 시점
OCustomer.name = "Dooly"
println("name = ${OCustomer.name}")
println(OCustomer.HOBBY.name)
CCustomer.greeting()
println("name = ${CCustomer.name}, HELLO = ${CCustomer.HELLO}")
println(CCustomer.HOBBY.name)
}
/*
object로 선언된 OCustomer는 멤버 프로퍼티와 메서드를 객체 생성 없이 이름의 점(.) 표기법으로 바로 사용할 수 있다.
이것 역시 단일 인스턴스를 생성해 처리하기 때문에 싱글톤 패턴에 이용된다.
object 선언 방식을 사용하면 접근 시점에서 객체가 생성된다.
그렇기 때문에 생성자 호출을 하지 않으므로 object 선언에는 주 생성자와 부 생성자를 사용할 수 없다.
하지만 초기화 블록인 init이 들어갈 수 있는데 최초 접근에서 실행된다.
object 선언에서도 클래스나 인터페이스를 상속할 수 있다.
* */
# Object 표현식 : object 표현식은 object 선언과 달리 이름이 없으며 싱글톤이 아니다. 따라서 object 표현식이 사용될 때마다 새로운 인스턴스가 생성된다. 결과적으로 이름이 없는 익명 내부 클래스로 불리는 형태를 object 표현식으로 만들 수 있다.
package chap02.section1
/* object 표현식 */
open class Superman() {
fun work() = println("Taking photos")
fun talk() = println("Talking with people.")
open fun fly() = println("Flying in the air")
}
fun main() {
val pretendedMan = object : Superman(){ // (1) object 표현식으로 fly() 함수 재정의
override fun fly() {
println("I'm a not a real SuperMan. I can't fly")
}
}
pretendedMan.work()
pretendedMan.talk()
pretendedMan.fly()
}
/*
(1)번에 익명 객체가 object 표현식으로 만들어졌다. 여기서 익명 객체는 Superman 클래스를 상속해 fly() 메서드를 오버라이딩하고 있다.
결국 하위 클래스를 만들지 않고도 Superman 클래스의 fly() 메서드를 오버라이딩해 변경했다.
* */
'Kotlin' 카테고리의 다른 글
Kotlin - 데이터 클래스(Java의 POJO)와 기타클래스 (0) | 2022.06.17 |
---|---|
Kotlin - 추상클래스와 인터페이스 ★ (0) | 2022.06.15 |
Kotlin - by(위임), 클래스의 위임 ★ (0) | 2022.06.15 |
Kotlin - 지연 초기화 ★ (0) | 2022.06.14 |
Kotlin - 프로퍼티의 접근 (0) | 2022.06.14 |