이 포스팅은 Kotlin in Action, 드미트리 제메로프 & 스베트라나 이사코바, 에이콘출판사(2017)을 읽고 개인 학습용으로 정리한 글입니다.
코틀린 인터페이스 안에 추상 메서드 뿐만 아니라 구현이 있는 메서드 정의 가능
인터페이스에는 아무런 상태(필드)도 들어갈 수 없다
클래스는 인터페이스를 개수 제한 없이 구현 가능, 클래스는 오직 하나만 확장 가능
override 변경자 꼭 사용해야
-> 상위 클래스에 있는 메서드와 시그니처가 같은 메서드를 우연히 하위 클래스에 선언 -> 컴파일 X
한 클래스에서 시그니처가 같은 메서드가 들어있는 두 인터페이스를 함께 구현
-> 두 메서드를 아우르는 구현을 하위 메서드에 직접 구현해야
상위 타입의 구현을 호출할 때 super 사용
-> super기반 클래스 이름
취약한 기반 클래스(fragile base class) 문제
-> 하위 클래스가 기반 클래스에 대해 가졌던 가정이 기반 클래스를 변경함으로써 깨져버린 경우 발생
코틀린의 클래스와 메서드는 기본적으로 final(상속 불가능)
-> 상속 허용하려면 클래스 앞에 open 변경자
-> 오버라이드 허용하고 싶은 메서드/프로퍼티 앞에도 open 변경자
오버라이드한 메서드는 기본적으로 열려있음
-> 오버라이드하는 메서드의 구현을 하위 클래스에서 오버라이드 하지 못하게 금지하려면 final 명시해야
abstract로 선언한 추상 클래스는 인스턴스화 X
추상 멤버는 항상 열려있다
-> 추상 멤버 앞에 open 변경자 명시할 필요 X
인터페이스 멤버의 경우 final, open, abstract 사용 X
-> 인터페이스 멤버 항상 열려있음
-> 인터페이스 멤버 final로 변경 X
-> 인스턴스 멤버 본문 없으면 자동으로 추상 멤버
아무 변경자도 없는 경우 선언 모두 public
코틀린 internal 가시성 변경자
-> 모듈 내부에서만 볼 수 있음
-> 모듈: 한꺼번에 컴파일되는 코틀린 파일들
-> 모듈의 구현에 대해 진정한 캡슐화 제공
어떤 클래스의 기반 타입 목록에 들어있는 타입 가시성 -> 클래스 자신의 가시성보다 같거나 높아야
제네릭 클래스의 타입 파라미터에 들어있는 타입의 가시성 -> 클래스 자신의 가시성보다 같거나 높아야
ex. public 클래스는 private 클래스를 자신의 기반 클래스로 가질 수 X
메서드의 시그니처에 사용된 모든 타입의 가시성 -> 그 메서드의 가시성보다 같거나 높아야
ex. public 메서드는 private 타입을 인자로 가질 수 X
자바에서는 클래스를 private으로 만들 수 X -> 내부적으로 패키지-전용 클래스로 컴파일
자바에는 internal 변경자에 딱 맞는 가시성 없음 -> 내부적으로 public으로 컴파일
-> 코틀린에서 접근할 수 없는 대상을 자바에서 접근할 수 있는 경우 생김
상위 클래스에 sealed 변경자를 붙이면 그 상위 클래스를 상속한 하위 클래스 정의 제한 가능
sealed 클래스의 하위 클래스를 정의할 때는 반드시 상위 클래스 안에 중첩시켜야
sealed 클래스에 속한 값에 대해 디폴트 분기를 포함하지 않고 when 식 사용
-> 나중에 sealed 클래스의 상속 계층에 새로운 하위 클래스 추가하면 when식 컴파일되지 X
초기화 블록: 클래스의 객체가 생성될 때 실행될 초기화 코드 들어감
초기화 블록은 주 생성자와 함께 사용됨
필요하다면 클래스 안에 여러 초기화 블록 선언 가능
클래스에 기반 클래스가 있다면 주생성자에서 기반 클래스의 생성자를 호출해야
클래스 정의에 있는 상위 클래스 및 인터페이스 목록에서
이름 뒤에 괄호가 있으면 기반 클래스, 없으면 기반 인터페이스
인터페이스에서 추상 프로퍼티를 선언하는 경우
-> 하위 클래스는 추상 프로퍼티를 반드시 오버라이드해야
인터페이스에서 세터와 게터가 있는 프로퍼티를 선언하는 경우
-> 게터와 세터는 뒷받침하는 필드를 참조할 수 X
코틀린에서 == 연산자는 참조 동일성을 검사하지 않고 객체 동등성을 검사
-> ==연산은 equals를 호출하는 식으로 컴파일
-> 참조 비교는 === 연산자 사용
a==b
a?.equals(B)?:(b==null)
HashMap 등의 컨테이너에 데이터 클래스나 객체를 담는 경우 불변성 필수적
copy메서드는 객체를 복사하면서 일부 프로퍼티를 바꿀 수 있게 해줌
-> 복사본은 원본과 다른 생명주기를 가짐
-> 원본을 참조하는 다른 부분에 전혀 영향X
데코레이터(Decorator) 패턴: 상속을 허용하지 않는 클래스(기존 클래스) 대신 사용할 수 있는 새로운 클래스(데코레이터) 만들기
-> 기존 클래스와 같은 인터페이스를 데코레이터가 제공
-> 기존 클래스를 데코레이터 내부에 필드로 유지
새로 정의해야 하는 기능은 데코레이터의 메서드에 새로 정의
기존 기능이 그대로 필요한 부분은 데코레이터의 메서드가 기존 클래스의 메서드에게 요청 전달(forwarding)
by 키워드: 인터페이스에 대한 구현을 다른 객체에 위임 중이라는 사실 명시 가능
자바의 싱글턴 패턴: 클래스의 생성자를 private으로 제한하고 정적인(static) 필드에 그 클래스의 유일한 객체 저장
코틀린의 싱글턴 패턴: 객체 선언
-> 클래스의 선언과 그 클래스에 속한 단일 인스턴스의 선언을 합친 선언
객체 선언에 생성자(주 생성자와 부 생성자 모두)는 쓸 수 X
-> 싱글턴 객체는 객체 선언문이 있는 위치에서 생성자 호출 없이 즉시 만들어짐
객체 선언도 클래스나 인터페이스 상속 가능
클래스 안에서 객체 선언 가능 -> 그런 객체도 인스턴스는 하나 뿐
-> 바깥 클래스의 인스턴스마다 중첩 객체 선언에 해당하는 인스턴스가 하나씩 따로 생기지 X
동반 객체의 프로퍼티나 메서드에 접근하려면 그 동반 객체가 정의된 클래스 이름 사용
동반 객체는 자신을 둘러싼 클래스의 모든 private 멤버에 접근 가능
동반 객체 멤버를 하위 크래스에서 오버라이드할 수 X
클래스의 동반 객체 안에 함수 정의 -> 클래스에 대해 호출할 수 있는 확장 함수
ex. C라는 클래스 안에 동반 객체가 있고 그 객체(C.Companion)안에 func를 정의하면
외부에서는 func()를 C.func()로 호출 가능
동반 객체에 대한 확장 함수를 작성할 수 있으려면 원래 클래스에 동반 객체를 꼭 선언해야
-> 빈 객체라도 동반 객체가 꼭 있어야
객체 선언과 달리 무명 객체는 싱글턴 X
-> 객체 식이 쓰일 때마다 새로운 인스턴스 생성됨
무명 객체 안에 여러 메서드를 오버라이드해야 하는 경우에 훨씬 유용