jongheonleee / kotlin

코틀린 학습

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

🦸🏻‍♀️ kotlin(코틀린)



🎯 공부하기 앞서서, FP의 중요성


OOP가 각광받은 이유는 변경 사항이 많이 발생했고 이를 효율적으로 대처하기 위함 그 이후는 멀티 코어와 멀티 쓰레드 환경에서 서비스가 돌아가고 데이터가 증가하여 빅데이터 시대가 도래함. 따라서, 이 데이터를 처리하기 위해 FP가 각광 받음

함수형 프로그래밍이 중요한 이유, 바로 빅데이터다 멀티 쓰레딩 환경에서 함수형 프로그래밍이 각광 받음 OOP의 경우 iv를 저장해서 공유함, 하지만 FP는 이를 지양함 FP에서 중요한 것은 두 가지

  • 불변 : 변경되지 않는 것
  • 순수함수 : 외부에 영향 x

=> 그 이유는, 빅데이터 처리 과정에서 되돌리기 쉬워야함. 예를들어서, 빅데이터를 처리하는 과정에서 오류가 발생하면 해당 작업을 멈추고 작업 전 상태로 다시 되돌아가야함. 그래서 순수함수가 중요한 것임(비순수함수의 경우 되돌리기가 어려움)



📋 목차

📌 01. 코틀린 기초 프로그래밍 : FP 특성(불변, 순수함수)을 살리려고 노력, 자바보다 유연함

📌 02. 코틀린과 객체지향 프로그래밍 :

📌 03. 코틀린과 함수형 프로그래밍 :

📌 04. 코틀린의 다양한 기법 :


📌 01. 코틀린 기초 프로그래밍 : FP 특성(불변, 순수함수)을 살리려고 노력, 자바보다 유연함

1. 코틀린 기본 작성법 : 파일과 클래스 둘 다 가능, 자바보다 유연함

👉 클래스 파일, 일반 파일(둘 다 확장자가 .kt)

  • 둘의 차이는 없음
  • 클래스 파일은 자바와 동일
  • 파일은 클래스 변수, 함수 구성
  • 코틀린 소스 -> 자바 소스 -> JVM 실행

👉 이름 변경해서 임포트 가능

  • import java.sql.Date as sqlDate
  • SQL에서 사용하는 AS 처럼 별명 부여해서 그걸로 사용 가능

2. 변수와 함수 : 불변과 순수함수를 처리하기 위해 노력

👉 변수 선언 var(read & write), val(read-only)

  • FP이기 때문에 불변이 중요함, 그래서 기본적으로 불변
    • 예를 들어서, 메서드의 매개변수는 변수 선언 x 이는 불변으로 선언하기 때문
  • 타입과 값을 분리해서 선언함
    • 코틀린에서는 타입 추론 가능함, 즉 타입을 선언부에 명시하지 않아도 값을 통해 해당 변수의 타입을 유추함
  • val는 상수가 아님, 프로퍼티 .. 이 있음, 즉 프로퍼티를 어떻게 설정하느냐에 따라 보여질 데이터 형식이 달라질 수 있음
    • 프로퍼티란? 특정 값에 getter/setter와 같은 특수 메서드들이 제공되는 형태, 즉 '데이터 + 함수'
    • const 를 통해 상수로 사용가능

👉 변수는 자동으로 초기화되지 않음, 코드에서 직접 초기화해야함

  • 코틀린에서는 자동으로 초기화하지 않음
  • 최상위 레벨/클래스의 멤버 변수 -> 선언과 동시에 초기화
    • 타입 추론이 가능하려면, 선언과 초기화를 동시에 함. 이때 선언부를 생략하는 형식
  • 함수 지역변수 -> 선언 / 초기화

👉 코틀린에서는 기본적으로 null 불가 -> null-safe

  • NPE 을 방지하기 위함
  • null이 될 수 있는 변수는 nullable 선언 -> '?'

👉 상수란 ? 값을 변경할 수 없고 항상 초기값만 반환하게 보장하는 변수

  • 코틀린에서 프로퍼티로 서로 다른 값을 반환하는 것을 강제해야함
  • const 예약어
    • var는 const 사용 불가
    • 최상위 레벨에서만 사용 가능

👉 fun으로 선언

  • 함수의 매개변수는 무조건 val 적용
    • FP의 중요한 개념인 '순수함수'
  • 매개변수에는 기본 인수 이용할 수 있음 fun some(amount : Int = 10)

👉 기본인수와 명명된 인수 지원

  • 기본 인수로 기본값 설정 가능
    • fun myFun(name : String = "Yeonuel", age : Int = 27)
  • n개 매개변수 -> 순서 혼란 -> 명명된 인수 해결
    • myFun(name = "Yeonuel", age = 27)

👉 중위 표현식, 중간에 함수를 위치 시킴

  • [중위 표현식]
  • 코틀린은 모든 것이 객체
  • 연산자를 피연산자의 중간에 위치시킴, infix 예약어
    • obj infixFun 10
  • infix 사용 가능한 경우
    • (1) 클래스의 멤버 함수로 선언/클래스의 확장 함수
    • (2) 매개변수가 하나인 함수

👉 가변인수(vararg)를 통해 오버로딩 작업 줄임

  • [가변 개수 매개변수]
  • 여러개 오버로딩 작업 -> 함수를 가변 인수를 포함하는 함수로 선언하면 쉽게 작성 가능

👉 재귀함수(tailrec), 재귀함수를 효율적으로 사용하기 위해 tailrec 활용

  • [tailrec 주의 상황]
  • tailrec -> 자바 while 문
    • 성능 개선
    • StackOverFlow 방지
  • tailrec 재귀함수에서 자신을 호출하는 구문은 함수의 맨 마지막 작업으로 작성
    • 위의 예시에서 첫 번째 함수는 tailrec으로 선언한 것에 의미가 없어짐

👉 자바의 final과 코틀린의 final 차이

  • 자바 : final은 불변을 정의할 때 주로 사용 -> 상수, 오버로딩 x, 상속 x
  • 물론, 둘 다 final이 클래스의 상속과 관련이 있음 하지만, 코틀린에서는 상수변수를 만들 때 final을 사용하지 않음
  • 코틀린에서는 val를 통해서 불변을 선언


3. 데이터 타입


👉 코틀린은 모든 것이 객체

  • 기초 타입 자체가 없음, 모든 것이 객체임
  • 코틀린에서는 Int, Double, Float, Long, Short, Byte, Char, Boolean, String, Any, Unit, Nothing
    • 숫자 타입 클래스들은 모두 Number의 서브 클래스
    • Number의 규칙
      • (1) Decimals, Hexadecimals, Binaries 값 대입 가능
      • (2) Long은 접미사 L 사용
      • (3) 실수 기본형은 Double
      • (4) 실수형 10.0e2로 표현 가능
      • (5) Float은 접미사 f, F 사용

👉 자바와 다른 부분

  • Char 타입은 Number로 표현 x
    • if (ch == 1) -> 컴파일 에러
  • 큰따옴표 세 개로 묶는 문자열(raw string)
    • [raw string]

👉 Any, Unit, Nothing

  • Any : 코틀린 클래스의 최상위 클래스, 자바의 Object와 유사

    • [Any와 Any?의 관계]
  • Unit : 반환 구문이 없음을 의미, 타입임, void와 유사

  • Nothing : 의미 있는 데이터가 없음을 명시적으로 선언


👉타입 확인과 캐스팅(is)

  • is : 타입 확인 연산자
    • 특정 타입으로 확인되면, 컴파일러가 자동으로 캐스팅하는 스마트 캐스트
  • 코틀린에서는 기초 데이터 타입에 대한 자동 형 변환 지원 x

👉컬렉션 타입 -> 배열/ List, Set, Map

  • [컬렉션 타입 별 불변/가변 함수]

  • 배열 : Array로 표현

    • [Array 선언]
    • 특정 타입을 명시하지 않으면, 배열 변수에는 다양한 타입의 데이터를 추가 할 수 있음
    • 지네릭을 이용하여 특정 데이터만 추가할 수 있게 제한 가능

  • 코틀린에선 Collection에 List, Set, Map 모두 표현

    • List : 순서 o, 중복 o
    • Set : 순서 x, 중복 x
    • Map : 키와 값, 순서 x, 키 중복 x
  • Collection을 크게 2가지로 분류

    • (1) 가변(mutable) : R & W
    • (2) 불변(immutable) : R, 기본값

  • [List 관련 인터페이스/클래스]
  • List, Map, Set, Array 타입의 데이터 모두 이터레이터 타입의 객체로 변형하여 이용할 수 있음
    • 해당 컬렉션 모두 iterator() 있음

👉 흐름 제어 구문과 연산자

  • if 문이 표현식임 -> 값을 만드는 문장, if 문에 의해 특정 값이 발생한다
    • 표현식 : 값을 만드는 문장
    • 구문 : 명령을 지시하는 문장
    • if 문을 표현식으로 쓸 경우, if 문에 {} 명시하여 여러줄 작성하면, 데이터는 맨 마지막에 작성해야함

  • when은 switch 문과 유사함, 또한 when은 표현식임
    • [when의 여러 형태]

  • for 반복문

    • [for 문의 여러 형태]
  • while 문은 다른언어와 같음


  • 전개 연산자(*)
    • *A : A 배열의 데이터를 나열
  • 범위 연산자(..)
    • A..B : A부터 B까지의 수를 묶어 범위 표현

  • 일치 연산자
    • ==, != -> 단순 값 비교
    • ===, !== -> 갹체 비교

  • 연산자 재정의 방법

    • 연산자에 대응하는 함수를 재정의하는 것
    • 이는 클래스의 멤버로 정의할 수 있고, 확장 함수로 추가하여 사용할 수도 있음
    • operator 예약어 활용
  • [연산자 재정의]

📌 02. 코틀린과 객체지향 프로그래밍 :

👉 07. 코틀린에서 생성자는 두 개 -> '주 생성자', '보조 생성자'


👉클래스의 대표 생성자인 주 생성자, 주 생성자와 실행 영역이 분리되어 있음

  • 주 생성자 : n개의 생성자 중에 대표 생성자
    • 하나의 클래스에 하나만 작성 가능
    • 클래스 선언 부분에 작성, 선언부에 동시에 주 생성자 실행 문을 쓸 수 없음 -> 클래스 몸체에 주 생성자 실행 영역 init{}이 존재
    • 필수는 아님, 보조 생성자가 있으면 작성 안해도됨
    • 별도의 생성자 없으면, 컴파일러가 자동으로 주 생성자 추가

  • 주 생성자의 여러 유형

    • [매개변수 없는 주 생성자]

    • [매개변수 있는 주 생성자]


    • [매개변수에 기본값 명시한 주 생성자]


  • 주 생성자는 헤더에 명시 -> 실행문을 같이 명시할 수 없읍 -> 클래스 내부의 init{} 사용
    • init{} : 주생성자의 실행 영역
    • [init 영역]

  • 초기화 블럭, 프로퍼티(iv)에서는 생성자 매개변수 사용 가능. 하지만, 멤버 함수에서는 사용 불가

    • [함수 생성자 매개변수 아용 에러]

    • 위의 문제를 해결할 2 가지 방법
      • (1) 클래스 프로퍼티(iv)에 대입 -> 함수에서 프로퍼티(iv) 이용

        • [클래스 프로퍼티에 대입]
      • (2) 생성자 내에서 val, var 이용

        • [생성자 매개변수 선언 시 var, val 이용]

👉 클래스의 몸체에 선언되는 보조 생성자

  • 클래스 몸체에 constructor 예약어로 선언
    • [보조 생성자]
    • 컴파일러는 보조 생성자나 주 생성자를 선언하지 않은 경우에만 주 생성자 자동 추가
    • 보조 생성자를 선언하면 주 생성자 선언안해도됨

👉 생성자 오버로딩 -> n개의 생성자를 선언

  • [생성자 오버로딩]

👉 실행 순서 : 주 생성자 -> 초기화 블럭(init{}) -> 보조 생성자

  • [보조 생성자와 초기화 블럭]

👉 init{}, 함수에서 보조 생성자의 매개변수에 접근할 수 없음

  • [보조 생성자의 매개변수]
  • 보조 생성자 내의 매개변수에는 val, var 선언을 못함
  • 결국, 보조 생성자의 매개변수를 클래스 멤버에서 이용하려면, 클래스 프로퍼티(iv)에 대입후 이용해야함

👉 this()에 의한 생성자 연결

  • 주 생성자 선언, 보조 생성자는 무조건 주 생성자를 함께 호출. 즉, 보조 생성자에 주 생성자 호출 구문이 있어야함
    • this()로 연결해주기
  • 주 생성자와 보조 생성자 함께 선언 -> 보조 생성자와 주 생성자를 this()로 연결
    • 주 생성자를 선언했다면, 반드시 주 생성자는 실행되야함
  • [주 생성자와 보조 생성자 연결 에러]
  • [보조 생성자와 주 생성자가 함께 선언된 경우]

  • [주 생성자와 보조 생성자 코드 흐름 1]

  • [주 생성자와 보조 생성자 코드 흐름 2]


👉 '주 생성자'와 '보조 생성자'를 구분해서 사용하는 이유?

  • 일단, 질문과 번외로 가독성 고려해서 굳이 '보조 생성자'를 사용할 필요가 없으면 '주 생성자'만을 사용하는게 좋음
  • '주 생성자'의 위치 -> 생성자는 중요한 구성 요소, 클래스 선언부에 위치해 놓는게 좋음
  • 생성자 오버로딩 ->'주 생성자' : 공통 매개변수(필수값), '보조 생성자' : 개별 매개변수(선택값)

👉 코틀린의 파일은 코드를 관리하는 수단일뿐임

  • 자바의 경우, 하나의 파일에 public이 추가된 클래스는 하나만 존재
  • 코틀린은 public 클래스 n개 가능, 즉 파일은 코드를 관리하는 수단일뿐 클래스와는 관련 없음

👉 코틀린에는 new 가 없음



👉 08. 코틀린에서 iv는 프로퍼티, getter/setter가 있는 객체


👉 코틀린은 모든 것이 객체, iv도 객체 이를 프로퍼티라고 말함

  • 프로퍼티 : 클래스의 변수(iv), 함수가 내장된 변수
    • 접근자 - getter/setter 가 내장되어 잇음
  • [프로퍼티 형식]

  • [클래스에서 프로퍼티]
  • var -> getter/setter 추가됨, val -> getter만 추가됨
  • 외부에서 get(), set() 명시적으로 호출하는 것이 아니라 변수값을 조회하거나 변경하면됨
    • 내부적으로는 get(), set() 호출

👉 접근자(getter/setter)를 사용하는 이유

  • OOP의 핵심 내용 중 하나인 캡슐화와 관련있음
    • 캡슐화 -> 정보은닉, 보호, 유지 보수성
    • 변수를 직접 다루는 것이 아니라, getter/setter로 간접적으로 다루는 것
  • 또한, 외부에서는 변수를 직접 다루는 것처럼 사용하지만, 실질적으로는 내부에서 getter/setter를 이용
  • 따라서, getter/setter 정의 하지 않아도됨

👉 사용자 정의 프로퍼티, 즉 getter/setter를 재정의

  • [사용자 정의 프로퍼티]

  • [사용자 정의 프로퍼티 잘못 사용

  • getter/setter 직접 정의 가능

  • 사용자 정의 프로퍼티 규칙

    • (1) 프로퍼티 값을 'field'로 접근
    • (2) var -> get(), set() 재정의 가능, val -> set() 재정의 불가능
    • (3) val -> get() 정의하면 초깃값 명시안해도됨
    • (4) var -> get() 정의해도 초깃값 명시해야함

👉 프로퍼티 -> 최상위 레벨 변수, 클래스 내부에 선언한 멤버 변수(iv)

  • [다양한 변수와 프로퍼티]
  • 모든 변수가 프로퍼티는 아님
  • lv는 프로퍼티 아님

👉 생성자에 var, val 로 선언한 변수에는 get(), set() 정의 할 수 없음

  • [주 생성자 프로퍼티 이용]
  • 원래는 안됨, 하지만 가능하게 하는 방법이 있음
  • 주 생성자의 매개변수를 클래스에 선언한 프로퍼티에 적용, 그 프로퍼티를 활용하면됨

👉 다양한 방식의 프로퍼티 초기화. 크게 5가지 방식

  • 원래 프로퍼티는 선언과 초기화 동시에 처리, 하지만 여러 방식들이 있음(4 가지 방식이 더 있음)

    • 일반적으로 프로퍼티는 선언과 초기화 동시에 처리 안하면 컴파일 에러 발생
  • 선언과 초기화 동시 처리 이외의 초기화 방식은 크게 4가지가 있음

    • (1) [초기화 블록에서 프로퍼티 초기화]

    • (2) [null 허용으로 선언]
    • '?' -> nullable 로 선언
    • null 로 초기화한 후 실제 데이터로 값을 변경

    • (3) [늦은 초기화]
    • 프로퍼티를 nullable 선언안하고 프로퍼티 초기화를 미룸, 이를 늦은 초기화
    • lateinit 키워드 사용, 그리고 규칙이 있음
      • (1) lateinit은 var 만 가능
      • (2) 주 생성자에 사용할 수 없음
      • (3) 사용자 정의 getter/setter 못함
      • (4) nullable 안됨
      • (5) 기초 타입 프로퍼티 사용 불가
        • [lateinit 사용 에러]

    • (4) [초기화 미루기]
    • 미리 정의는 해두지만 미룸
    • by lazy {} 로 선언, 프로퍼티가 이용되는 시점에 해당 영역 실행됨
    • 프로퍼티 선언하면서 초기화하는 것을 미룸, 사용 시점에 초기화 실행
    • lazy의 규칙
      • (1) 호출 시점에 초기화 실행
      • (2) val 로 선언한 프로퍼티에만 사용 가능
      • (3) 클래스 몸체, 최상위 레벨에서 사용 가능
      • (4) 기초 타입에도 가능

👉 초기화 시점을 미루는 이유

  • 코틀린에서는 null 처리가 엄격함
  • null 대입하지 않을 프로퍼티에 null 대입했다가 추후에 초기화하는 것은 불필요한 작업
  • null 허용하지 않는 프로퍼티인데 초기화를 나중에 하는 경우는 많음
    • DI, 의존성 주입

👉 프로퍼티 값 변경 감지, 변경 -> 특정 코드 실행

  • [프로퍼티 observable]
  • 'by Delegates.observable(초기값, 실행문(람다))'

👉 코틀린에서는 필드가 없음

  • 필드 : 클래스의 멤버 데이터, 별도로 지정하지 않는 한 정적이지 않음
    • 하나의 클래스 내에서만 사용하고자 하는 변수(iv)
  • 프로퍼티 : 사용자가 설정할 수 있는 객체의 특성
    • 외부에서 이용을 위해 getter/setter 를 포함한 변수(iv + 접근자)


👉 09. 상속


👉 Any 클래스 -> equals(), toString(), hashCode() 만 제공하는 최고조상


👉 상속을 통한 클래스 정의

  • [상위 클래스/하위 클래스]
  • open 키워드, 콜론(:) 사용
  • 코틀린은 기본적으로 final 로 상속을 막아둠
    • 상속 허용 여부 명시하지 않으면 기본적으로 final 적용
    • final 의미
      • (1) final 클래스 : 상속 x
      • (2) final 함수 : 함수 오버라이드 x
      • (3) final 프로퍼티 : 프로퍼티 오버리이드 x

👉 오버라이드 -> 함수, 프로퍼티

  • [상위 클래스/하위 클래스]
  • 오버라이드 : 상위 클래스의 프로퍼티나 함수 -> 하위 클래스에서 재정의
  • 상위에서는 해당 타겟이 open으로 열려있어야함
  • 하위에서는 override를 통해서 오버라이함
    • override로 정의한 함수는 자동으로 open 상태
      • 하위에서 오버라이드 막으려면 final 사용, 즉 final override 사용해야함

  • 프로퍼티 오버라이드 규칙
    • (1) 상위 클래스의 프로퍼티, 이름, 타입 일치
    • (2) val -> var, val 가능
    • (3) var -> var 가능
    • (4) nullable -> null 불가 가능
    • (5) null 불가 -> nullable 불가능

👉 상위 클래스 멤버 접근, 상위 클래스 생성자 호출 -> super.멤버, super()

  • [상속에 의한 생성자]

  • [상위 클래스 생성자 연결]
  • 생성자 간의 관계
    • (1) 주 생성자 선언, 해당 클래스의 보조 생성자에서는 주 생성자와 연결하기 위해 this() 구문이 추가되야함
    • (2) 객체 생성 시 어떤 식으로든 상위 클래스의 생성자는 호출되어야함

  • [상하위 생성자의 수행 흐름]
  • 생성자가 호출되는 순서
    • (1) this(), super()에 의해 다른 생성자 호출
    • (2) init {} 호출
    • (3) 생성자의 {} 실행

👉 스마트 캐스팅 -> 타입 확인되면 그 타입으로 자동 변환

  • 스마트 캐스팅 : 명시적으로 캐스팅을 선언하지 않아도 자동으로 캐스팅되는 것
    • is 는 스마트 캐스팅 : 타입 체크 + 스마트 캐스팅

👉 as를 이용한 캐스팅, 명시적 캐스팅

  • 코틀린에는 자동 캐스팅 없음
  • 상속 관계에 있는 객체를 명시적으로 캐스팅할 때는 'as' 키워드 사용
  • [형식]

  • 'as?'를 사용하면, nullable 객체에 객체가 대입되면 캐스팅, 그렇지 않으면 null 반환

👉 접근 제한자, 각 요소별로 상이함

  • [최상위 구성요소의 접근 제한자]

  • [클래스 멤버의 접근 범위]

  • [프로퍼티의 접근 제한자]

  • 주 생성자와 보조 생성자 모두 접근 제한자를 지정할 수 있음
  • 상속 관계에 의한 접근 제한자 지정 규칙
    • (1) open과 private 동시에 사용 x
      • 최상위 파일에서는 가능, 또한 해당 클래스의 하위 클래스 구현시 똑같은 접근 제한자 써야함(private)
    • (2) 하위 클래스에서 상위 멤버를 오버라이드할 때 접근 범위를 줄일 수 없음

👉 코틀린에서의 상속이 자바의 상속과 다른 부분

  • (1) 최상위 클래스 Any
  • (2) 세미 콜론(:) 사용
  • (3) 기본값 final, 상속 ... 처리하려면 open 사용
  • (4) 명시적 캐스팅 -> as

📌 03. 코틀린과 함수형 프로그래밍 :

📌 04. 코틀린의 다양한 기법 활용 :

About

코틀린 학습


Languages

Language:Kotlin 100.0%