객체와 싱글톤(object)객체 표현식(object expression)으로 사용하는 익명 객체supertype으로부터 익명객체를 상속하기객체 선언(object declartion)을 이용한 싱글톤탑레벨 함수 vs 싱글톤Object declartion 에서 상속클래스 생성필드와 속성lateinit vs lazy속성 제어 변경 (setter 커스텀 정의)접근 제어자초기화 블럭주 생성자보조 생성자주 생성자에게 위임컴패니언 객체와 클래스 멤버클래스 레벨 멤버컴패니언에 접근하기팩토리로 사용하는 컴패니언static 과는 다르다제네릭 클래스 생성데이터 클래스
객체와 싱글톤(object)
- 개발자가 필요하다면 클래스 정의 없이 객체를 생성할 수 있다. 간단한 상황이면 객체를 바로 사용할 수 있고, 추상클래스를 정의해야하는 복잡한 상황인 경우엔 클래스를 정의한 후 만들어서 사용할 수 있다.
객체 표현식(object expression)으로 사용하는 익명 객체
- 대부분의 객체 표현식은 지역변수들을 그룹핑 할 때만 유용하다
supertype으로부터 익명객체를 상속하기


Object declarations and expressions | Kotlin
A singleton ensures that a class has only one instance and provides a global point of access to it.
- 작은 변화만 주면
익명 객체는 인터페이스의 구현체가 된다
- 익명 내부 클래스가 둘 이상의 인터페이스를 구현해야 한다면
object: Runnable, AutoCloseable
과 같이 콤마로 구분하면 됨
객체 선언(object declartion)을 이용한 싱글톤
- object 키워드와 {} 블록 사이에 이름을 넣는다면, 코틀린은 이를 표현식이 아니라 명령문 또는 선언 으로 인식하고 싱글톤 객체를 만들어 준다
- 위의 코드를 입력함으로써 Util은 이미 객체인 상태이고 클래스로 취급되지 않음. Java의 private 생성자와 static 메서드만 가지고 있는 클래스라 생각하면 됨
- 싱글톤은 메서드만 가질 수 있는게 아니라 val과 var 로 선언된 속성 모두 가질 수 있음
- 싱글톤에 뮤터블한 상태를 갖는 것은 멀티스레드 애플리케이션에서 문제를 유발할 수 있다.
탑레벨 함수 vs 싱글톤
- 사용할 함수들이 하이레벨이거나 일반적이거나 넓게 사용될 예정이라면 패키지 안에 직접 넣어서 탑레벨 함수로 사용하는게 좋다.
- 반대로 함수들이 서로 연관되어 있다면 싱글톤을 사용하는 게 좋다.
- 만약 함수들이 상태와 연관되어 있다면 싱글톤이 좋지만, 클래스가 더 좋은 선택일 가능성이 크다.
프로그램의 행동, 계산, 작동에 집중할 때 함수와 싱글톤이 적절. 하지만 상태를 다뤄야 한다면 클래스를 사용하는 게 더 좋은 선택
Object declartion 에서 상속
- object declartion을 이용하면 변수에 할당을 할 수 없고 → local 일수 없고 함수내에서 nested로 사용이 불가능한 것(object expression 과 달리)
클래스 생성
- class 생성 시, val이나 var 로 정의하면 속성이 되고, 그냥 명시하면 생성자의 파라미터로만 이용이 됨
필드와 속성
Java에서는 위의 yearOfMake와 color가 속성보다는 필드에 가까움
그러나 이것들은 모두 필드가 아니고 속성이다. 코틀린에서는 클래스에 필드가 없다.
(필드와는 달리 프로퍼티는 get/set 접근자를 통해 멤버 변수에 접근하게 함)
- 위의 코드를 컴파일해서 클래스 파일을 확인해보면 car.yearOfMake 로 접근할 때, getYearOfMake() 함수를 호출해서 값을 가지고 옴. 그리고 필드들은 private으로 선언되어 있음
- 코틀린에서는 getter,setter 대신 속성의 이름을 이용해서 속성에 접근할 수 있음
lateinit vs lazy
- lateinit : var 사용. 초기화 이후에 계속해서 값이 바뀔 수 있을 때 [ Kotlin docs 참고 ]
- 해당 필드가 초기화되었는지 확인하기 위해서
.isInitialized
를 참조해보기 - 선언과 초기화가 분리되어 있음
- by lazy : val 사용. 초기화 이후에 읽기 전용 값으로 사용할 때
- 선언과 초기화가 같이 있음
lazy
프로퍼티 연산은 기본적으로 동기화된다.
속성 제어 변경 (setter 커스텀 정의)
getter와 setter가 자동생성되지만, 아래와 같이 커스텀하게 작성할 수 있음
- 여기서 속성은 yearOfMake, fuelLevel, color 3개 속성이 있음
- 스페셜 키워드인
field
를 이용하여 참조되고 있는 필드에 값을 할당할 수 있음
- 파라미터 value는 다른 이름이어도 상관 없음
접근 제어자
코틀린에서 클래스의 속성과 메서드는 public 이 기본
public, private, protected, internal 네 개의 접근 제어자. 처음 두 개는 Java와 동일
protected는 파생(자식)클래스들의 메소드가 속성에 접근할 수 있는 권한
internal은 같은 모듈(함께 컴파일된 모든 소스 코드)에 있는 모든 소스 코드에서 속성이나 메소드에 접근 가능
- getter의 접근 권한은 속성의 접근 권한과 동일
- setter의 접근권한은 개발자가 원하는 대로 설정 가능함
초기화 블럭
주 생성자는 첫번째 블록에 나타남. 객체를 초기화하는 코드가 값들을 설정하는 것보다 더 복잡하다면 생성자용 바디를 만들 필요가 있음.
- init 블록은 주 생성자의 실행의 한 부분으로써 실행됨
- init 블록의 코드는 top-down 순으로 순차적으로 실행
- init 블록은 여러 개 정의할 수 있지만 필요할 때만 정의하기
- 클래스 안에서 첫 번째로 속성을 가장 위에 정의, 그 후 init 블록(필요한 경우), 그리고 보조 생성자 구현(필요한 경우)
주생성자의 파라미터는 initializer block 내부에서 사용될 수 있음. 또한 property를 초기화 하는데도 사용가능함
주 생성자
보조 생성자
- 주 생성자를 작성하지 않았다면 코틀린은 아규먼트가 없는 기본 생성자를 생성
- 만약 주 생성자가 모든 파라미터를 위한 기본 아규먼트를 갖고 있다면 코틀린은 주 생성자와 함께 아규먼트가 없는 생성자를 생성
- 보조 생성자의 파라미터도 역시 val 이나 var를 사용할 수 없다. 보조 생성자에는 속성 선언할 수 없기에
주 생성자에게 위임
주 생성자가 없다 하더라도 delegation은 암묵적으로 일어나고, 초기화 블럭은 수행이 됨
컴패니언 객체와 클래스 멤버
클래스 레벨 멤버
컴패니언에 접근하기
val ref = MachineOperator.Companion
그러나 컴패니언 객체에 이름을 지정하면 그것으로 참조가 가능함. 이름지정하지 않을때는
Companion
으로 참조팩토리로 사용하는 컴패니언
static 과는 다르다
컴패니언 객체의 멤버에 접근하면 코틀린 컴파일러는 싱글톤 객체로 라우팅을 한다. 그런데 Java와의 상호 운용성 측면에서 봤을 때 이런 동작은 문제를 야기할 수 있다.
코틀린엔 static 메서드가 없다. 가장 가까운 것이 컴패니언 객체의 함수인데, 이를 Java에서 쉽게 사용하기 위해 코틀린 컴파일러에게 이 메소드들을 바이트코드에 static으로 만들라는 지시를 해줘야 함
- 싱글톤이나 컴패니언 객체에 속한 메서드를 만들 때 Java에서 static 메서드로 접근을 쉽게 할 수 있도록 할 필요가 있는지 스스로에게 질문 후 그럴필요가 있을 때만
@JvmStatic
붙이기
제네릭 클래스 생성
데이터 클래스
- 특정한 행동, 동작보다는 데이터를 옮기는 데 특화된 클래스임
- 주 생성자에는 val이나 var를 사용한 속성 정의가 적어도 하나 이상 필요
- equals(), hashCode(), toString() 메서드를 자동으로 만들어줌
- component1(), component2() 등의 메서드를 자동으로 만들어주고, 이 메서드들의 주된 목적은 구조분해임