- Kotlin의 기본 선언은 final, public
- 중첩 클래스는 내부 클래스가 아니다
4.1 클래스 계층 정의
- 코틀린 인터페이스
- 추상메서드 뿐 아니라 디폴트 구현이 있는 메소드도 정의 가능
- public static final class로 만든 후 내부 메서드로 구현
- override 변경자 필수 사용
- 같은 이름의 메소스 구현시 오버라이딩 메소드를 직접 제공하지 않으면 에러 발생
- super<타입> 으로 구현
- 자바에서는 코틀린의 디폴트 메서드 구현에 의존할 수 없다.
- 일반 인터페이스와 디폴트 메서드 구현이 정적 메서드로 들어있는 클래스를 조합해 구현
- 멤버가 항상 열려있다. final, open, abstract 사용 안함
- 추상메서드 뿐 아니라 디폴트 구현이 있는 메소드도 정의 가능
- open, final, abstarct 변경자
- 취약한 기반 클래스
- 기반이 되는 클래스 변경시 하위 클래스의 동작이 예기치 않게 바뀌는 문제
- 해결 방안: 문서를 잘 갖출 수 없다면, 상속을 금하라
- 상속을 허용하려면 open 변경자 사용
- 하위 클래스에서 override한 메서드의 상속을 막으려면 final 변경자 사용
- 장점으로 스마트 캐스트가 가능하다. / 커스텀 접근자를 정의함으로써 요구 사항을 깨는 것을 방지
- 취약한 기반 클래스
- 가시성 변경자
- 코틀린은 패키지를 네임스페이스 관리용으로만 사용
- 모듈: 한꺼번에 컴파일되는 코틀린 파일
- 가시성 변경자 종류
- public: 기본 가시성 / 모든 곳
- internal: 같은 모듈 / 같은 모듈
- 자바에서는 public 처리
- 멤버의 이름을 kotlin$KotlinInAction()과 같이 바꿈
- protected: 하위 클래스 안에서만
- 자바는 같은 패키지 안에서 접근 가능하지만, 코틀린은 하위 클래스만
- private: 같은 클래스 안에서만 / 같은 파일 안에서만
- 코틀린 private - 자바 package-private
- 메서드 시그니처나 타입 들은 기반타입의 가시성이 본인과 같거나 높아야 한다.
- 모든 타입에 접근할 수 있도록 보장하기 위함
- 외부 클래스가 내부 클래스나 중첩된 클래스의 priavte에 접근 할 수 없다.
- 내부 클래스와 중첩된 클래스 : 기본적으로 중첩 클래스
- 코틀린에서 아무것도 붙지 않으면 자바의 static 중첩 클래스와 같다.
- 내부 클래스로 변경하여 바깥참조를 포함하고 싶으면 inner 변경자를 붙여야 한다.
- 봉인된 클래스: 클래스 계층 정의 시 계층 확장 제한
- 상위 클래스에 sealed 변경자를 붙이면 그 상위 클래스를 상속한 하위 클래스 정의를 제한
- when의 분기에 활용하는데 좋다.
- 상위 클래스에 sealed 변경자를 붙이면 그 상위 클래스를 상속한 하위 클래스 정의를 제한
4.2 뻔하지 않은 생성자와 프로퍼티를 갖는 클래스 선언
- 코틀린은 주 생성자와 부 생성자로 구분한다.
- 초기화 블록을 통해 초기화 로직을 추가할 수 있다.
- 클래스 초기화: 주 생성자와 초기화 블록
- 클래스 명 뒤에 오는 괄호로 둘러쌓인 코드를 주 생성자
- 생성자 파라미터 지정 및 프로퍼티를 정의
- constructor :주, 부 생성자 정의
- 생략 조건: 주 생성자 앞에 별도의 애노테이션이나 가시성 변경자가 없으면 생략 가능
- init: 초기화 블럭
- 프로퍼티 선언에 포함 시킬수 있는 경우
- 디폴트 값 정의 가능
- new 키워드 없이 인스턴스 생성
- 모든 생성자 파라미터에 디폴트 값을 지정하면 컴파일러가 파라미터가 없는 생성자를 만든다.
- DI의 경우 파라미터가 없는 생성자를 통해 객체를 생성해야만 라이브러리가 사용이 가능한 경우가 있는데 그 경우에 좋다.
- 하위 클래스는 기반 클래스의 생성자를 호출해야 하므로 이름 뒤에 빈 괄호가 들어가는 것
- 클래스 외부에서 인스턴스화를 막고 싶다면 constructor() 앞에 private를 붙이면 된다.
- 유틸리티 함수를 담는 클래스에 사용
- 클래스 명 뒤에 오는 괄호로 둘러쌓인 코드를 주 생성자
- 부 생성자: 상위 클래스를 다른 방식으로 초기화
- 클래스의 확장하기 위한 방안으로 다양한 생성자를 지원해야하는 경우
- contructor를 이용해 부 생성자를 만든다.
- 클래스에 주 생성자가 없다면 모든 부 생성자는 반드시 상위 클래스를 초기화 하거나, 다른 생성자에게 생성을 위임해아한다.
- 부 생성자가 필요한 이유: 상호 운용성
- 인터페이스에 선언된 프로퍼티 구현
- getter,settter가 있는 프로퍼티 선언 가능
- 게터와 세터에서 뒷받침하는 필드에 접근
- 변경 가능 프로퍼티에서 한쪽만 직접 정의해도 된다.
- 접근자의 가시성 변경
- 접근자의 가시성은 프로퍼티와 같다.
- public으로 선언해서 get은 가능하지만, set을 private으로 놓아서 변경을 fun addWord로만 가능하게 한다.
4.3 컴파일러가 생성한 메소드 : 데이터 클래스와 클래스 위임
- equals, hashCode, toString을 컴파일러가 안보이는 곳에서 생성
- 모든 클래스가 정의해야 하는 메소드
- 코틀린에서는 == 는 eqauls를 호출(동등성 비교) ===가 참조를 비교
- eqauls override시 hashcode도 override 해줘야 한다.
- 데이터 클래스 : 모든 클래스가 정의해야 하는 메소드 자동 생성
- data class라고 선언
- 내부적으로 * 31 해가면서 hashCode 구현 / 31인 이유 : 소수이면서 shift연산 - i 한 것과 같아서 최적화 가능
- val로 만들어서 불변클래스로 만들것을 권장 / 동기화 문제 해결
- copy: 객체를 복사하면서 일부 프로퍼티 변경 가능한 메소드
- data class라고 선언
- 클래스 위임: by 키워드 사용
- 상위 클래스의 메소드 변경시 하위 클래스에서 갖고 있던 가정이 깨져 작동하지 않는 경우를 해소하기 위한 목적
- 상속을 허용하지 않는 클래스에 새로운 동작을 추가해야할 때 일반적인 방법이 데코레이터 패턴
4.4 object 키워드 : 클래스 선언과 인스턴스 생성
- 클래스를 정의하면서 인스턴스를 생성
- companion object: 클래스와 관련있는 메소드와 팩토리 메소드를 담을 때
- 자바의 무명 내부 클래스 대신
- 객체 선언: 싱글턴을 쉽게 만들기
- 객체 선언 기능을 통해 싱글턴 패턴을 지원
- 객체 선언: 클래스 선언과 단일 인스턴스 선언을 합친 선언
- 자바에서는 static INSTANCE 변수를 만들어서 static 블럭에서 초기화
- 프로퍼티, 메소드, 초기화 블록 등이 들어갈 수 있다.
- 생성자는 객체 선언에 쓸 수 없다.
- 객체를 인자로 받는곳에서 사용가능하다.
- 대규모에서 싱글턴은 객체 생성을 제어할 방법이 없고 생성자 파라미터를 지정할 수 없어서 적합하지 않다.
- 비교하는 클래스를 내부에 정의하는 것이 바람직하다.
- 객체 선언 기능을 통해 싱글턴 패턴을 지원
- 동반 객체: 팩토리 메소드와 정적 멤버가 들어갈 장소
- 자바의 static 키워드를 지원하지 않는다. 대신 최상위 함수와 객체 선언을 활용
- 동반 객체는 자신을 둘러싼 클래스의 private 멤버에 접근 가능 / private 생성자를 호출하기 좋은 위치
- 자바에서는 static
- 동반 객체는 팩토리 패턴을 구현하기 가장 적합한 위치
- 생성할 필요가 없는 객체를 생성하지 않을 수 있다.
- 동반 객체를 일반 객체처럼 사용
- 동반 객체는 클래스 안에 정의된 일반 객체다.
- 이름을 붙이거나, 인터페이스 상속, 확창 함수와 프로퍼티 정의 가능
- 자바에서 사용하기 위해 코틀린 클래스의 멤버를 정적인 멤버로 만들려면 @JvmStatic 어노테이션 사용
- 클래스.companion.확장함수를 이용해 외부에서 정의할 수 있다.
- 대신 비어있는 companion object가 있어야 한다.
- 동반 객체는 클래스 안에 정의된 일반 객체다.
- 객체 식: 무명 내부 클래스를 다른 방식으로 작성
- 자바에서 무명 내부 클래스와 같이 이름이 없다.
- 이름이 필요하면 변수에 대입
- 무명 객체 안에서 로컬 변수의 사용이 가능하다.
- 무명 객체는 싱글턴이 아니라 쓰일 때마다 새로운 인스턴스 생성
- 메소드가 하나뿐인 인터페이스를 구현해야 한다면, SAM 인터페이스와 람다를 사용해서 구현
- 자바에서 무명 내부 클래스와 같이 이름이 없다.
'Kotlin' 카테고리의 다른 글
Kotlin In Action - 6. 코틀린 타입 시스템 (0) | 2024.05.27 |
---|---|
Kotlin In Action - 5. 람다로 프로그래밍 (0) | 2024.05.26 |
Kotlin in Action - 함수 정의와 호출 (0) | 2024.05.17 |
Kotlin in Action - 2. 코틀린 기초 (0) | 2024.05.15 |
Kotlin In Action - 코틀린이란 무엇이며, 왜 필요한가? (0) | 2024.05.06 |