보통, 클래스로부터 생성되는 객체(서로 연관 있는 변수(속성) 들을 묶어놓은 데이터 덩어리)는 heap에 저장이 됩니다.
객체를 참조하는 변수는 stack 영역에 생성되어 그 객체의 주소를 가지고 있습니다.
val d1 = MyClass() //MyClass 객체는 Heap 영역에 생성되고, stack 영역에 변수 d1에 대한 메모리를 확보하고, MyClass 의 주소를 갖게 됩니다.
- Stack 영역은 컴파일 시점에 크기가 결정되는 영역 (매개변수, 지역변수 등),
- Heap 영역은 런타임에 크기가 결정되는 영역이다. (동적할당, 객체 등)
object 키워드에 대해 알아 보겠습니다.
익명 객체
//object 키워드가 우변에 있을 경우 익명객체
//MyFunc 함수 호출시에 heap에 생성되었다가 함수가 완료되면 heap에서 완료됨
fun MyFunc() {
val myObj = object {
val a = 10
val b = 10
}
println(myObj.a)
}
싱글톤 객체
object SingleTon {
val a : Int = 10
}
print(SingleTon.a)
//Java
public class SingleTon {
private static SingleTon mSingleton;
private int a = 10;
public static SingleTon getInstance() {
if (mSingleton == null) {
mSingleton = new SingleTon();
}
return mSingleton;
}
}
힙 영역에 SingleTon이라는 객체는 하나만 생성됩니다.코틀린에서는 object 키워드만 붙이면 간단하게 싱글톤 패턴으로 된 객체를 생성할 수 있습니다. (Enum class도 동일함)
이렇게 선언된 객체는 프로그램 전체에서 공유할 수 있는 하나뿐인 객체 입니다.
object MyObject {
const val a : Int = 10 //const 키워드는 top level이나 object에서만 붙일 수 있다.
}
class MyClass {
val a : Int = 10
}
fun main(args: Array<String>) {
val obj = MyObject
println(obj.a)
println(MyObject.a)
println(MyClass.a) //error ; 객체 생성 없이 바로 참조 불가능하다.
}
클래스 객체안에서 생성할 수도 있습니다.
* Person안에 object NameComparator를 만들었습니다. Person 인스턴스마다 객체 선언에 해당하는 인스턴스가 생성되는게 아니라, 단 하나의 객체선언 인스턴스만 생성됩니다.
그래서 Person.NameComparator으로 객체 선언된 NameComparator를 사용할 수 있습니다.
data class Person(val name: String) {
object NameComparator : Comparator<Person> {
override fun compare(p1: Person, p2: Person): Int = p1.name.compareTo(p2.name)
}
}
fun main(args: Array<String>) {
val persons = listOf(Person("하지마"), Person("변여름"), Person("나태웅"))
println(persons.sortedWith(Person.NameComparator))
companion object (동반 객체)
Java나 C#과는 달리, 코틀린에는 static 멤버 변수나 함수가 없습니다. 만약 클래스 인스턴스없이 어떤 클래스 내부에 접근하고 싶다면, 클래스 내부에 객체를 선언할 때 companion 식별자를 붙인 object를 선언하면 됩니다.
아래 예에서 클래스내에 선언된 MyComp 라는 객체는 heap에 하나만 생성되어 여러 MyClass 객체들이 공유를 할 수 있게 됩니다.
//companion object
class MyClass {
companion object MyComp {
fun getValue(value: Int) {
for(i in 1..value)
print(i)
}
}
}
MyClass1.MyComp.getValue(5)
companion object는 어떤 클래스의 모든 인스턴스가 공유하는 객체를 만들고 싶을 때 사용하며, 클래스당 한 개만 가질 수 있습니다
companion object 이름이 없는 경우 Companion 식별자를 사용할 수 있습니다. 이름이 있는 경우는 사용할 수 없습니다.
//companion object
class MyClass1{
companion object {// MyComp { //object 이름을 주석처리
fun getValue(value: Int) {
for(i in 1..value)
println(i)
}
}
}
fun main(args: Array<String>) {
val x = MyClass1.Companion.getValue(5)
val y = MyClass1.getValue(5) //Companion 는 굳이 안 붙여도 됩니다.
클래스 안에 private 로 선언된 프로퍼티나 메소드 혹은 생성자가 있을 경우 그 클래스 외부에서는 접근할 수 없습니다. 하지만 companion object 로 만들어진 동반 객체는 바깥쪽 클래스의 private 데이터에도 접근이 가능합니다. 그리고 이 동반객체를 호출하면 private로 선언된 데이터를 사용할 수 있습니다.
data class Person private constructor(val name: String) {
companion object cObj {
fun newPerson(cName: String) = Person(cName)
}
}
fun main(args: Array<String>) {
val person = Person.cObj.newPerson("가지마")
println(person.name)
}
'Kotlin' 카테고리의 다른 글
SubsamplingScaleImageView (0) | 2022.04.23 |
---|---|
Animation (0) | 2022.04.18 |
확장함수 (Extension Function) (0) | 2022.04.14 |
코루틴(Coroutine) (0) | 2022.04.03 |
BlogViewer (feat. JSoup Crawling) (1) | 2022.04.03 |