[Kotlin] 클래스를 알아보자 (클래스와 프로퍼티 심화편)

2025. 11. 6. 22:47·Android

클래스와 프로퍼티 간단한 정리

코틀린의 클래스는 비공개 필드, 공개 게터, (선택적으로) 공개 세터를 디폴트로 제공합니다.

class Person(
	val name: String, // 비공개 필드, 공개 게터
	var isMarried: Boolean // 비공개 필드, 공개 게터, 공개 세터
)

👇

person.name = "new name" // ❌ 불가능
person.isMarried = true // ⭕ 가능

 

+ 비공개 필드란, 프로퍼티가 저장되는 곳입니다.

필드는 비공개하여 직접 접근을 막는 대신 getter/setter를 통해 값을 읽거나 쓸 수 있게 해요.

 

커스텀 접근자도 만들 수 있어요.

내부적으로 관리가 필요하지 않지만, 외부에서 알고싶은 값에 사용하면 될 것 같아요.

class Rectangle (val height: Int, val width: Int) {
	val isSquare: Boolean
		get() = height == width
}

 

Data Class

특징

- 상속 불가

- 1개 이상의 프로퍼티 필수로 가져야 함

 

유용한 메서드

- copy() ⭐

data class HomeUiState (
    val myProfile: Profile? = null,
    val otherProfiles: List<Profile> = listOf()
)

class HomeViewModel : ViewModel() {
    private val _uiState = MutableStateFlow(HomeUiState())
    val uiState: StateFlow<HomeUiState> = _uiState.asStateFlow()

    init {
        getMyProfile()
        getOtherProfiles()
    }

    fun getMyProfile() {
        _uiState.value = _uiState.value.copy(
            myProfile = myProfile
        )
    }

    fun getOtherProfiles() {
        _uiState.value = _uiState.value.copy(
            otherProfiles = homeProfiles
        )
    }
}

 

- toString()

data class Rectangle (
    val height: Int,
    val width: Int
)

fun main() {
   val rec = Rectangle(3, 4)
   println(rec)
}

// 결과 : Rectangle(height=3, width=4)

 

- hashCode()

data class Rectangle (
    val height: Int,
    val width: Int
)

fun main() {
   val rec1 = Rectangle(3, 4)
   val rec2 = Rectangle(3, 4)
   val rec3 = Rectangle(32, 42)

   println(rec1.hashCode()) // 97
   println(rec2.hashCode()) // 97
   println(rec3.hashCode()) // 1034
   
   val recSet = setOf(rec1, rec2, rec3)
   println(recSet) // [Rectangle(height=3, width=4), Rectangle(height=32, width=42)]
}

 

- equals()

data class Rectangle (
    val height: Int,
    val width: Int
)

fun main() {
   val rec1 = Rectangle(3, 4)
   val rec2 = Rectangle(3, 4)

   println(rec1 == rec2) // true (equals())
   println(rec1 === rec2) // false
}

 

 

Interface

특징

- 클래스의 규칙을 정의하는 타입/계약

- 객체를 만들 수 없음

- 다른 클래스를 통해 구현됨

 

예제

- 레포지토리 추상화 "UserRepository를 구현하는 클래스는 반드시 getUserInfo 메서드를 제공한다"

interface UserRepository {

    suspend fun getUserInfo() : UserResponse

}

 

인터페이스 규칙에 따라 실제 레포지토리 구현

// 네트워크 연동된 구현체
class UserRepositoryImpl (
    private val userDataSource: UserDataSource,
) : UserRepository {

    override suspend fun getUserInfo(
    ) = userDataSource.getUserInfo()

}

// 테스트용 Mock 구현체
class MockUserRepository : UserRepository {

    override suspend fun getUserInfo(
    ) = UserResponse(name = "dodo", part = "android")

}

 

레포지토리를 사용하는 ViewModel은 인터페이스인 UserRepository로 레포지토리를 받아옴

인터페이스가 getUserInfo 메서드를 보장하므로 호출 가능

class HomeViewModel (
    private val userRepository: UserRepository,
) : ViewModel() {
    private val _uiState = MutableStateFlow(HomeUiState())
    val uiState: StateFlow<HomeUiState> = _uiState.asStateFlow()

    private fun getUserInfo() {
        viewModelScope.launch {
            val userInfo = userRepository.getUserInfo()
            _uiState.value = _uiState.value.copy(
            )
        }
    }
}

 

인터페이스를 사용했기 때문에 HomeViewModel의 코드를 전혀 수정하지 않고도

상황에 따라 구현체를 넣어줌으로서 동작을 변경할 수 있음

 

Sealed Class

개념

- 추상 클래스

- 자신을 상속받는 여러 개의 서브 클래스를 제한적으로 가질 수 있음

 

특징

- enum class의 확장

sealed class UIState {
    data object Loading : UIState()
    data class Success(val data: String) : UIState()
    data class Error(val exception: Exception) : UIState()
}

fun updateUI(state: UIState) {
    when (state) {
        is UIState.Loading -> showLoadingIndicator()
        is UIState.Success -> showData(state.data)
        is UIState.Error -> showError(state.exception)
    }
}

enum class와 달리 클래스 별로 다른 프로퍼티를 가질 수 있음

 

UIState를 상속받는 클래스가 정확히 Loading, Success, Error 3개로 보장

외부에서 임의로 상속 불가하며, when에서 else를 사용하지 않아도 오류가 발생하지 않음

'Android' 카테고리의 다른 글

[Kotlin] Kotlin in Action 3장. 함수 정의와 호출  (0) 2025.11.12
[Kotlin] Kotlin in Action 2장. 코틀린의 기초  (0) 2025.11.02
[Kotlin] Kotlin in Action 1장. 코틀린이란 무엇이며, 왜 필요한가?  (0) 2025.10.26
'Android' 카테고리의 다른 글
  • [Android] 업데이트 안 해도 아이콘을 요리조리 바꾸는 법 (Dynamic App Icon / feat. 듀오링고)
  • [Kotlin] Kotlin in Action 3장. 함수 정의와 호출
  • [Kotlin] Kotlin in Action 2장. 코틀린의 기초
  • [Kotlin] Kotlin in Action 1장. 코틀린이란 무엇이며, 왜 필요한가?
오카룽
오카룽
Dart/Flutter, Kotlin, Android Jetpack, Jetpack Compose
  • 오카룽
    Okarun.dev
    오카룽
  • 전체
    오늘
    어제
    • 분류 전체보기 (20)
      • Architecture (1)
      • Android (14)
      • Flutter (0)
      • Collaboration (2)
      • Launching (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • Github
  • 공지사항

  • 인기 글

  • 태그

    dynamic icon
    android
    jetpack compose
    github
    이미지 해상도 관리
    list state
    스크롤 방향
    스크롤
    안드로이드
    sticky header
    Kotlin
    slack
    android studio
    Actions
    lazy column
    플로팅
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
오카룽
[Kotlin] 클래스를 알아보자 (클래스와 프로퍼티 심화편)
상단으로

티스토리툴바