선생님, 개발을 잘하고 싶어요.

Kotlin in Action - 1부 4장 - 클래스, 객체, 인터페이스 본문

일상/책 리뷰

Kotlin in Action - 1부 4장 - 클래스, 객체, 인터페이스

알고싶은 승민 2022. 5. 21. 16:46

다루는 거

  • 코틀린과 자바의 클래스 선언 차이
    • 기본적으로 final public
    • 의도적 상속가능성 open
    • 모듈 레벨 가시성 internal
    • 바깥 클래스 참조를 포함하는 중첩 클래스는 inner
    • 같은 파일에서만 상속이 가능한 sealed
  • 프로퍼티의 뒷받침 필드 참조를 위한 field
  • data class
  • 클래스 위임으로 보일러 플레이트 코드 줄이기
  • object 싱글턴
  • companion object
  • 무명 내부 클래스

클래스 계층 정의

코틀린 인터페이스는 자바 8 인터페이스와 비슷하다.

구현이 있는 메서드도 정의할 수 있다. 자바 8의 디폴트 메서드와 비슷하다.

interface 키워드로 정의한다.

클래스 이름 뒤에 콜론(:)을 붙히고 인터페이스와 클래스 이름을 적는 것이 끝

상위 클래스나 인터페이스에 있는 프로퍼티나 메서드를 오버라이드 한다면 override 변경자를 반드시 사용해야한다. 실수로 부모 클래스의 메서드를 오버라이드 하는 경우를 방지해준다.

interface Clickable {
  fun click()
  fun showOff() = println("나여")
}

특정 상위 타입의 멤버 메서드를 호출할지 결정할 수 있다.

class Button : Clickable, Focusable {
  override fun showOff() {
    super<Clickable>.showOff()
    super<Focusable>.showOff()
  }
}

코틀린은 자바 6과 호환되게 설계했고, 자바 6은 디폴트 메서드를 지원하지 않는다. 따라서 코틀린은 일반 인터페이스와 디폴트 메서드 구현이 정적 메서드로 들어있는 클래스를 조합해서 구현한다.

코틀린 인터페이스 디폴트 구현
별도의 static 함수로 제공

상속을 제어하는 변경자: open, final, abstract, override : 기본은 final

하위 클래스가 기반 클래스에 대해 가진 가정이 기반 클래스를 변경하므로써 깨지는 문제를 취약한 기반 클래스 문제라고 한다. 상속을 위한 설계와 문서를 갖추거나 그럴 수 없다면 상속을 금지하라는 원칙을 따른다.

코틀린 클래스와 메서드는 기본적으로 final이다. 즉 기본은 상속 금지

상속을 허용하려면 open 변경자 붙히기

추상 멤버를 정의하려면 abstract 변경자 붙히기 추상 멤버는 오버라이드 해야만 하므로 항상 open이다.

가시성 변경자: 기본은 public

코틀린에는 패키지 전용 가시성이 없다. 패키지를 네임스페이스를 관리하기 위한 용도로만 사용한다.

internal 키워드는 모듈 내에서만 볼수 있음을 의미한다, 모듈은 한 번에 한꺼번에 컴파일되는 코틀린 파일을 의미한다.

최상위 선언에 대해 private 가시성을 허용한다. 파일 내부에서만 사용할 수 있다.

확장 함수에서는 해당 클래스의 protected, private 필드에 접근할 수 없다.

자바에는 internal이 없으므로 그냥 public으로 만들어진다. 코틀린 컴파일러가 internal 멤버 이름을 보기 나쁘게 바꾼다.

내부 클래스와 중첩된 클래스: 기본적으로 중첩 클래스

코틀린의 중첩 클래스(nested class)는 명시적으로 요청하지 않는 한 바깥쪽 클래스 인스턴스에 대한 접근 권한이 없다.

inner class → 바깥 클래스의 참조를 묵시적으로 포함한다.

중첩 클래스는 아무런 변경자가 붙지 않고 자바의 static 중첩 클래스와 같다.

클래스 계층을 만들되 그 계층에 속한 클래스의 수를 제한하고 싶은 경우 중첩 클래스를 쓰면 편리

sealed class: 클래스 계층 확장 제한

sealed class의 하위 클래스를 정의할 때는 반드시 상위 클래스가 정의된 파일 안에 있어야한다.

sealed interface도 있네!

뻔하지 않은 생성자와 프로퍼티를 갖는 클래스 : 주 생성자, 부 생성자, 초기화 블록

주 생성자와 초기화 블록

class User constructor(_nickname: String) { // 파라미터가 하나인 주 생성자
  val nickname: String

  init { // 초기화 블록, 여러 개 만들 수 있다.
		nickname = _nickname
	}
}

// 위의 구현과 일치
class User(val nickname: String)

부 생성자: 다른 방식으로 초기화

코틀린의 디폴트 파라미터와 이름 붙힌 인자 문법을 사용하면 자바의 오버라이드 생성자가 필요한 대부분ㅇ의 상황을 해결할 수 있다.

주 생성자가 없다면 모든 부 생성자는 반드시 상위 클래스를 초기화하거나 다른 생성자에게 생성을 위임해야한다. 그 화살표의 마지막에는 항상 상위 클래스 생성자 호출이 있어야한다.

파라미터 목록이 다른 생성 방법이 여럿 존재하는 경우에는 부 생성자를 여럿 둘 수밖에 없다.

게터와 세터에 뒷받침하는 필드에 접근 field

직접 게터나 세터를 정의하건 관계없이 게터나 세터에 field를 사용하는 프로퍼티에 대해 뒤받침하는 필드를 생성한다. 만약 field 접근 안하면, 뒷받침 필드 자체를 안만든다 !

컴파일러가 생성한 메서드: data class와 클래스 위임

보일러 플레이트 코드를 자동 생성해주는 IDE 지원이 있지만, 코틀린은 그런 코드를 아예 컴파일러 차원에서 해결한다.

문자열 표현을 위한 toString,

객체의 동등성 체크를 위한 equals,

해시 컨테이너 hashCode

equals가 true를 반환하는 객체는 hashCode가 같아야한다.

HashSet의 경우 원소 비교를 위해서 hashCode를 비교하고 이 값이 같은 경우에만 모든 원소를 비교하는 식으로 비용을 줄인다.

코틀린에서 객체의 동등성 표현은 ==로 참조 비교를 위해서는 ===를 사용한다.

어떤 클래스가 데이터를 저장하는 역할만 수행한다면? data class를 정의하면된다.

copy 메서드도 제공된다. 불변 객체로 더 쉽게 활용할 수 있게 코틀린 컴파일러가 제공하는 편의 메서드다.

클래스 위임: by 키워드 사용

상속을 허용하지 않는 클래스에 새로운 동작을 추가 → 데코레이터 패턴

새로운 클래스를 만들고 기존 클래스와 같은 인터페이스를 데코레이터가 제공하게 만들고 기존 클래스를 데코레이터 내부에 필드로 유지하는 것, 변경하고 싶은 동작은 변경하고 나머지는 기존 클래스에 forwarding 한다.

위임을 언어가 제공하는 일급 시민 기능으로 지원한다. *by 키워드를 통해 인터페이스에 대한 구현을 다른 객체에 위임 중이라는 걸 명시*한다.

컴파일러가 자동으로 해줄 수 있는 작업을 굳이 직접 해야 할 이유가 없다.

object 키워드: 클래스 선언과 인스턴스 생성

코틀린에선 다양한 상황에 object 키워드를 사용하지만 클래스를 정의하면서 동시에 인스턴스를 생성한다는 공통점이 있다.

  • 객체 선언 (object) 싱글턴을 정의하는 방법 중 하나
  • 동반 객체 (companion object) 인스턴스 메서드는 아니지만, 어떤 클래스와 관련 있는 메서드와 팩토리 메서드를 담을 때 쓰인다.
  • 무명 내부 클래스 대신 사용

object 싱글턴을 쉽게 만들기

인스턴스 하나만 필요한 클래스가 유용한 경우

생성자는 사용할 수 없음

  • 객체 생성을 제어할 방법이 없고
  • 생성자 파라미터를 지정할 수 없으므로

의존관계가 복잡한 대규모 시스템에선 의존성 주입 프레임워크를 함께 사용해야한다.

companion object, 팩토리 메서드와 정적 멤버가 들어갈 장소

코틀린은 자바의 static 키워드를 지원하지 않는다.

대신 코틀린은 패키지 수준의 최상위 함수와 객체 선언을 제공한다.

하지만 최상위 함수는 private으로 표시된 클래스 비공개 멤버에 접근할 수 없다.

그럴 때는 중첩된 객체 선언해야함.

클래스 안에 정의된 객체 중 하나에 companion이라는 특별한 표시를 붙히면 그 클래스를 동반 객체로 만들 수 있다.

동반 객체의 프로퍼티나 메서드에 접근하려면 그 동반 객체가 정의된 클래스 이름을 사용한다. 이는 자바의 정적 메서드 호출이나 정적 필드 사용 구문과 같아지는 효과가 있다.

동반 객체도 마찬가지로, 자신을 둘러싼 클래스의 모든 private 멤버에 접근할 수 있다. (outer class의 Private 생성자에도 접근 가능!)

동반 객체는 클래스 안에 정의된 일반 객체다.

다루는 거

  • 코틀린과 자바의 클래스 선언 차이
    • 기본적으로 final public
    • 의도적 상속가능성 open
    • 모듈 레벨 가시성 internal
    • 바깥 클래스 참조를 포함하는 중첩 클래스는 inner
    • 같은 파일에서만 상속이 가능한 sealed
  • 프로퍼티의 뒷받침 필드 참조를 위한 field
  • data class
  • 클래스 위임으로 보일러 플레이트 코드 줄이기
  • object 싱글턴
  • companion object
  • 무명 내부 클래스

클래스 계층 정의

코틀린 인터페이스는 자바 8 인터페이스와 비슷하다.

구현이 있는 메서드도 정의할 수 있다. 자바 8의 디폴트 메서드와 비슷하다.

interface 키워드로 정의한다.

클래스 이름 뒤에 콜론(:)을 붙히고 인터페이스와 클래스 이름을 적는 것이 끝

상위 클래스나 인터페이스에 있는 프로퍼티나 메서드를 오버라이드 한다면 override 변경자를 반드시 사용해야한다. 실수로 부모 클래스의 메서드를 오버라이드 하는 경우를 방지해준다.

interface Clickable {
  fun click()
  fun showOff() = println("나여")
}

특정 상위 타입의 멤버 메서드를 호출할지 결정할 수 있다.

class Button : Clickable, Focusable {
  override fun showOff() {
    super<Clickable>.showOff()
    super<Focusable>.showOff()
  }
}

코틀린은 자바 6과 호환되게 설계했고, 자바 6은 디폴트 메서드를 지원하지 않는다. 따라서 코틀린은 일반 인터페이스와 디폴트 메서드 구현이 정적 메서드로 들어있는 클래스를 조합해서 구현한다.

상속을 제어하는 변경자: open, final, abstract, override : 기본은 final

하위 클래스가 기반 클래스에 대해 가진 가정이 기반 클래스를 변경하므로써 깨지는 문제를 취약한 기반 클래스 문제라고 한다. 상속을 위한 설계와 문서를 갖추거나 그럴 수 없다면 상속을 금지하라는 원칙을 따른다.

코틀린 클래스와 메서드는 기본적으로 final이다. 즉 기본은 상속 금지

상속을 허용하려면 open 변경자 붙히기

추상 멤버를 정의하려면 abstract 변경자 붙히기 추상 멤버는 오버라이드 해야만 하므로 항상 open이다.

이미지 @@@@@@@@@@@@@@@@@@@@@

가시성 변경자: 기본은 public

코틀린에는 패키지 전용 가시성이 없다. 패키지를 네임스페이스를 관리하기 위한 용도로만 사용한다.

internal 키워드는 모듈 내에서만 볼수 있음을 의미한다, 모듈은 한 번에 한꺼번에 컴파일되는 코틀린 파일을 의미한다.

최상위 선언에 대해 private 가시성을 허용한다. 파일 내부에서만 사용할 수 있다.

확장 함수에서는 해당 클래스의 protected, private 필드에 접근할 수 없다.

자바에는 internal이 없으므로 그냥 public으로 만들어진다. 코틀린 컴파일러가 internal 멤버 이름을 보기 나쁘게 바꾼다.

내부 클래스와 중첩된 클래스: 기본적으로 중첩 클래스

코틀린의 중첩 클래스(nested class)는 명시적으로 요청하지 않는 한 바깥쪽 클래스 인스턴스에 대한 접근 권한이 없다.

inner class → 바깥 클래스의 참조를 묵시적으로 포함한다.

중첩 클래스는 아무런 변경자가 붙지 않고 자바의 static 중첩 클래스와 같다.

클래스 계층을 만들되 그 계층에 속한 클래스의 수를 제한하고 싶은 경우 중첩 클래스를 쓰면 편리

sealed class: 클래스 계층 확장 제한

sealed class의 하위 클래스를 정의할 때는 반드시 상위 클래스가 정의된 파일 안에 있어야한다.

sealed interface도 있네!

뻔하지 않은 생성자와 프로퍼티를 갖는 클래스 : 주 생성자, 부 생성자, 초기화 블록

주 생성자와 초기화 블록

class User constructor(_nickname: String) { // 파라미터가 하나인 주 생성자
  val nickname: String

  init { // 초기화 블록, 여러 개 만들 수 있다.
		nickname = _nickname
	}
}

// 위의 구현과 일치
class User(val nickname: String)

부 생성자: 다른 방식으로 초기화

코틀린의 디폴트 파라미터와 이름 붙힌 인자 문법을 사용하면 자바의 오버라이드 생성자가 필요한 대부분ㅇ의 상황을 해결할 수 있다.

주 생성자가 없다면 모든 부 생성자는 반드시 상위 클래스를 초기화하거나 다른 생성자에게 생성을 위임해야한다. 그 화살표의 마지막에는 항상 상위 클래스 생성자 호출이 있어야한다.

파라미터 목록이 다른 생성 방법이 여럿 존재하는 경우에는 부 생성자를 여럿 둘 수밖에 없다.

게터와 세터에 뒷받침하는 필드에 접근 field

직접 게터나 세터를 정의하건 관계없이 게터나 세터에 field를 사용하는 프로퍼티에 대해 뒤받침하는 필드를 생성한다. 만약 field 접근 안하면, 뒷받침 필드 자체를 안만든다 !

컴파일러가 생성한 메서드: data class와 클래스 위임

보일러 플레이트 코드를 자동 생성해주는 IDE 지원이 있지만, 코틀린은 그런 코드를 아예 컴파일러 차원에서 해결한다.

문자열 표현을 위한 toString,

객체의 동등성 체크를 위한 equals,

해시 컨테이너 hashCode

equals가 true를 반환하는 객체는 hashCode가 같아야한다.

HashSet의 경우 원소 비교를 위해서 hashCode를 비교하고 이 값이 같은 경우에만 모든 원소를 비교하는 식으로 비용을 줄인다.

코틀린에서 객체의 동등성 표현은 ==로 참조 비교를 위해서는 ===를 사용한다.

어떤 클래스가 데이터를 저장하는 역할만 수행한다면? data class를 정의하면된다.

copy 메서드도 제공된다. 불변 객체로 더 쉽게 활용할 수 있게 코틀린 컴파일러가 제공하는 편의 메서드다.

클래스 위임: by 키워드 사용

상속을 허용하지 않는 클래스에 새로운 동작을 추가 → 데코레이터 패턴

새로운 클래스를 만들고 기존 클래스와 같은 인터페이스를 데코레이터가 제공하게 만들고 기존 클래스를 데코레이터 내부에 필드로 유지하는 것, 변경하고 싶은 동작은 변경하고 나머지는 기존 클래스에 forwarding 한다.

위임을 언어가 제공하는 일급 시민 기능으로 지원한다. *by 키워드를 통해 인터페이스에 대한 구현을 다른 객체에 위임 중이라는 걸 명시*한다.

컴파일러가 자동으로 해줄 수 있는 작업을 굳이 직접 해야 할 이유가 없다.

object 키워드: 클래스 선언과 인스턴스 생성

코틀린에선 다양한 상황에 object 키워드를 사용하지만 클래스를 정의하면서 동시에 인스턴스를 생성한다는 공통점이 있다.

  • 객체 선언 (object) 싱글턴을 정의하는 방법 중 하나
  • 동반 객체 (companion object) 인스턴스 메서드는 아니지만, 어떤 클래스와 관련 있는 메서드와 팩토리 메서드를 담을 때 쓰인다.
  • 무명 내부 클래스 대신 사용

object 싱글턴을 쉽게 만들기

인스턴스 하나만 필요한 클래스가 유용한 경우

생성자는 사용할 수 없음

  • 객체 생성을 제어할 방법이 없고
  • 생성자 파라미터를 지정할 수 없으므로

의존관계가 복잡한 대규모 시스템에선 의존성 주입 프레임워크를 함께 사용해야한다.

companion object, 팩토리 메서드와 정적 멤버가 들어갈 장소

코틀린은 자바의 static 키워드를 지원하지 않는다.

대신 코틀린은 패키지 수준의 최상위 함수와 객체 선언을 제공한다.

하지만 최상위 함수는 private으로 표시된 클래스 비공개 멤버에 접근할 수 없다.

그럴 때는 중첩된 객체 선언해야함.

클래스 안에 정의된 객체 중 하나에 companion이라는 특별한 표시를 붙히면 그 클래스를 동반 객체로 만들 수 있다.

동반 객체의 프로퍼티나 메서드에 접근하려면 그 동반 객체가 정의된 클래스 이름을 사용한다. 이는 자바의 정적 메서드 호출이나 정적 필드 사용 구문과 같아지는 효과가 있다.

동반 객체도 마찬가지로, 자신을 둘러싼 클래스의 모든 private 멤버에 접근할 수 있다. (outer class의 Private 생성자에도 접근 가능!)

동반 객체는 클래스 안에 정의된 일반 객체다.

다루는 거

  • 코틀린과 자바의 클래스 선언 차이
    • 기본적으로 final public
    • 의도적 상속가능성 open
    • 모듈 레벨 가시성 internal
    • 바깥 클래스 참조를 포함하는 중첩 클래스는 inner
    • 같은 파일에서만 상속이 가능한 sealed
  • 프로퍼티의 뒷받침 필드 참조를 위한 field
  • data class
  • 클래스 위임으로 보일러 플레이트 코드 줄이기
  • object 싱글턴
  • companion object
  • 무명 내부 클래스

클래스 계층 정의

코틀린 인터페이스는 자바 8 인터페이스와 비슷하다.

구현이 있는 메서드도 정의할 수 있다. 자바 8의 디폴트 메서드와 비슷하다.

interface 키워드로 정의한다.

클래스 이름 뒤에 콜론(:)을 붙히고 인터페이스와 클래스 이름을 적는 것이 끝

상위 클래스나 인터페이스에 있는 프로퍼티나 메서드를 오버라이드 한다면 override 변경자를 반드시 사용해야한다. 실수로 부모 클래스의 메서드를 오버라이드 하는 경우를 방지해준다.

interface Clickable {
  fun click()
  fun showOff() = println("나여")
}

특정 상위 타입의 멤버 메서드를 호출할지 결정할 수 있다.

class Button : Clickable, Focusable {
  override fun showOff() {
    super<Clickable>.showOff()
    super<Focusable>.showOff()
  }
}

코틀린은 자바 6과 호환되게 설계했고, 자바 6은 디폴트 메서드를 지원하지 않는다. 따라서 코틀린은 일반 인터페이스와 디폴트 메서드 구현이 정적 메서드로 들어있는 클래스를 조합해서 구현한다.

상속을 제어하는 변경자: open, final, abstract, override : 기본은 final

하위 클래스가 기반 클래스에 대해 가진 가정이 기반 클래스를 변경하므로써 깨지는 문제를 취약한 기반 클래스 문제라고 한다. 상속을 위한 설계와 문서를 갖추거나 그럴 수 없다면 상속을 금지하라는 원칙을 따른다.

코틀린 클래스와 메서드는 기본적으로 final이다. 즉 기본은 상속 금지

상속을 허용하려면 open 변경자 붙히기

추상 멤버를 정의하려면 abstract 변경자 붙히기 추상 멤버는 오버라이드 해야만 하므로 항상 open이다.

이미지 @@@@@@@@@@@@@@@@@@@@@

가시성 변경자: 기본은 public

코틀린에는 패키지 전용 가시성이 없다. 패키지를 네임스페이스를 관리하기 위한 용도로만 사용한다.

internal 키워드는 모듈 내에서만 볼수 있음을 의미한다, 모듈은 한 번에 한꺼번에 컴파일되는 코틀린 파일을 의미한다.

최상위 선언에 대해 private 가시성을 허용한다. 파일 내부에서만 사용할 수 있다.

확장 함수에서는 해당 클래스의 protected, private 필드에 접근할 수 없다.

자바에는 internal이 없으므로 그냥 public으로 만들어진다. 코틀린 컴파일러가 internal 멤버 이름을 보기 나쁘게 바꾼다.

내부 클래스와 중첩된 클래스: 기본적으로 중첩 클래스

코틀린의 중첩 클래스(nested class)는 명시적으로 요청하지 않는 한 바깥쪽 클래스 인스턴스에 대한 접근 권한이 없다.

inner class → 바깥 클래스의 참조를 묵시적으로 포함한다.

중첩 클래스는 아무런 변경자가 붙지 않고 자바의 static 중첩 클래스와 같다.

클래스 계층을 만들되 그 계층에 속한 클래스의 수를 제한하고 싶은 경우 중첩 클래스를 쓰면 편리

sealed class: 클래스 계층 확장 제한

sealed class의 하위 클래스를 정의할 때는 반드시 상위 클래스가 정의된 파일 안에 있어야한다.

sealed interface도 있네!

뻔하지 않은 생성자와 프로퍼티를 갖는 클래스 : 주 생성자, 부 생성자, 초기화 블록

주 생성자와 초기화 블록

class User constructor(_nickname: String) { // 파라미터가 하나인 주 생성자
  val nickname: String

  init { // 초기화 블록, 여러 개 만들 수 있다.
		nickname = _nickname
	}
}

// 위의 구현과 일치
class User(val nickname: String)

부 생성자: 다른 방식으로 초기화

코틀린의 디폴트 파라미터와 이름 붙힌 인자 문법을 사용하면 자바의 오버라이드 생성자가 필요한 대부분ㅇ의 상황을 해결할 수 있다.

주 생성자가 없다면 모든 부 생성자는 반드시 상위 클래스를 초기화하거나 다른 생성자에게 생성을 위임해야한다. 그 화살표의 마지막에는 항상 상위 클래스 생성자 호출이 있어야한다.

파라미터 목록이 다른 생성 방법이 여럿 존재하는 경우에는 부 생성자를 여럿 둘 수밖에 없다.

게터와 세터에 뒷받침하는 필드에 접근 field

직접 게터나 세터를 정의하건 관계없이 게터나 세터에 field를 사용하는 프로퍼티에 대해 뒤받침하는 필드를 생성한다. 만약 field 접근 안하면, 뒷받침 필드 자체를 안만든다 !

컴파일러가 생성한 메서드: data class와 클래스 위임

보일러 플레이트 코드를 자동 생성해주는 IDE 지원이 있지만, 코틀린은 그런 코드를 아예 컴파일러 차원에서 해결한다.

문자열 표현을 위한 toString,

객체의 동등성 체크를 위한 equals,

해시 컨테이너 hashCode

equals가 true를 반환하는 객체는 hashCode가 같아야한다.

HashSet의 경우 원소 비교를 위해서 hashCode를 비교하고 이 값이 같은 경우에만 모든 원소를 비교하는 식으로 비용을 줄인다.

코틀린에서 객체의 동등성 표현은 ==로 참조 비교를 위해서는 ===를 사용한다.

어떤 클래스가 데이터를 저장하는 역할만 수행한다면? data class를 정의하면된다.

copy 메서드도 제공된다. 불변 객체로 더 쉽게 활용할 수 있게 코틀린 컴파일러가 제공하는 편의 메서드다.

클래스 위임: by 키워드 사용

상속을 허용하지 않는 클래스에 새로운 동작을 추가 → 데코레이터 패턴

새로운 클래스를 만들고 기존 클래스와 같은 인터페이스를 데코레이터가 제공하게 만들고 기존 클래스를 데코레이터 내부에 필드로 유지하는 것, 변경하고 싶은 동작은 변경하고 나머지는 기존 클래스에 forwarding 한다.

위임을 언어가 제공하는 일급 시민 기능으로 지원한다. *by 키워드를 통해 인터페이스에 대한 구현을 다른 객체에 위임 중이라는 걸 명시*한다.

컴파일러가 자동으로 해줄 수 있는 작업을 굳이 직접 해야 할 이유가 없다.

object 키워드: 클래스 선언과 인스턴스 생성

코틀린에선 다양한 상황에 object 키워드를 사용하지만 클래스를 정의하면서 동시에 인스턴스를 생성한다는 공통점이 있다.

  • 객체 선언 (object) 싱글턴을 정의하는 방법 중 하나
  • 동반 객체 (companion object) 인스턴스 메서드는 아니지만, 어떤 클래스와 관련 있는 메서드와 팩토리 메서드를 담을 때 쓰인다.
  • 무명 내부 클래스 대신 사용

object 싱글턴을 쉽게 만들기

인스턴스 하나만 필요한 클래스가 유용한 경우

생성자는 사용할 수 없음

  • 객체 생성을 제어할 방법이 없고
  • 생성자 파라미터를 지정할 수 없으므로

의존관계가 복잡한 대규모 시스템에선 의존성 주입 프레임워크를 함께 사용해야한다.

companion object, 팩토리 메서드와 정적 멤버가 들어갈 장소

코틀린은 자바의 static 키워드를 지원하지 않는다.

대신 코틀린은 패키지 수준의 최상위 함수와 객체 선언을 제공한다.

하지만 최상위 함수는 private으로 표시된 클래스 비공개 멤버에 접근할 수 없다.

그럴 때는 중첩된 객체 선언해야함.

클래스 안에 정의된 객체 중 하나에 companion이라는 특별한 표시를 붙히면 그 클래스를 동반 객체로 만들 수 있다.

동반 객체의 프로퍼티나 메서드에 접근하려면 그 동반 객체가 정의된 클래스 이름을 사용한다. 이는 자바의 정적 메서드 호출이나 정적 필드 사용 구문과 같아지는 효과가 있다.

동반 객체도 마찬가지로, 자신을 둘러싼 클래스의 모든 private 멤버에 접근할 수 있다. (outer class의 Private 생성자에도 접근 가능!)

동반 객체는 클래스 안에 정의된 일반 객체다.

Comments