코틀린 기본 익히기

hyeon·2022년 9월 13일
0

코틀린 스터디

목록 보기
1/5

Do it 코틀린 프로그래밍 책을 바탕으로 Kotlin에 대해 스터디를 진행합니다.

코틀린 시작하기

코틀린의 장점

  1. 자료형 오류를 미리 잡을 수 있는 정적언어이다.
    컴파일될 때 자료형을 검사하여 확정하기때문에 자료형 오류를 초기에 발견할 수 있다.
정적언어와 동적언어?
1. 정적언어 : 자료형을 컴파일시에 결정하는것 (ex c,c++,java)
	컴파일시에 결정하기 때문에 속도가 빠르다. 타입에러 문제를 초기에 발견할 수 있다.
2. 동적언어 : 실행시에 자료형을 결정. 자료형 없이 변수만 선언하여 값을 지정할 수 있음(ex python js)
	런타임에 타입을 결정하기 때문에 선택의 여지가 많음. 하지만 실행 도중 변수에 예상치 못한 타입이 들어와 타입에러가 생길 수 있음
  1. 널포인터 예외로 인한 프로그램 중단을 예방 할 수 있다.
코틀린은 널포인터가 일어날 수 있는 상황에서는 컴파일이 되지않는다 
var name: String ="abc"
name=null //컴파일 에러 발생
  1. 간결하고 효율적이다. (생략된 표현이 가능한 언어이다)
  2. 함수형 프로그래밍과 객체지향 프로그래밍이 모두 가능하다.(다중 패러다임 언어)
  3. 세미콜론 생략가능

변수와 자료형, 연산자

코틀린의 자료형

- val, var로 선언할 수 있다.

val : 최초로 지정한 변수의 값으로 초기화 하고 더이상 바꿀 수 없는 읽기전용 변수가 됨
var : 반면 var은 바꿀 수 있다. 
```
ex)
val username: String ="Kildong"
```

- 자료형을 추론 할 수있다.

"Kildong"을 보고 string이라고 추론한다.
    ex)
    val username="Kildong"

자료형을 지정하지 않은 변수는 추론할 값을 지정해야한다.

- 코틀린은 참조형 자료형을 사용한다.

    참조형과 기본형?
    기본형으로 선언한 변수는 주로 임시 메모리인 스택에 저장되며 메모리 크기도 고정되어있다.
    참조형은 스택에 값이 아닌 참조 주소가 있다. 참조주소를 따라가면 힙에 저장된 실제 객체가 있다. 그래서 기본형이 수행시간이 더 빠르다. 
	기본형(Primitive)은 int long float double
    참조형(Reference)는 String Date

참조형으로 선언된 변수는 성능 최적화를 위해 코틀린 컴파일러에서 다시 기본형으로 대체된다. => 참조형을 서서 느릴것같지만 컴파일과정에서 기본형으로 바귀기 때문에 최적화 고려할 필요 X

- String Pool

같은 문자열이 저장되어 있는 경우 힙영역의 String pool에 해당 문자열을 저장해두고 변수가 참조하도록 만든다. ===연산자를 사용하여 참조비교하면 true가 반환된다.

- 값이나 표현식을 넣어 출력하려면 $ 기호를 사용한다.

var a=1
val s1="a is $a"

표현식을 문자열에 포함하려면
val str="a=${a+2}"
이런식으로 사용한다.

- typealias 사용가능

typealias Username=String //String을 Username이라는 별명으로 대체 

- null 관련

- 변수에 null을 할당하려면 자료형 뒤에 ?를 붙여줘야함
```
var str: String?="Hello Kotlin"
str=null
```
- 세이프 콜 : null이 할당되어 있을 가능성이 있는 변수를 검사하여 안전하게 호출하도록 도와주는 기법. 변수 이름 뒤에 ?. 명시
```
println("str: $str leng: ${str?.length}
//null이라면 length에 접근하지 않고 null 출력
```
- non-null 단정기호 : 변수에 할당된 값이 null이 아니라고 단정하여 컴파일러가 null검사 하지않게함 (null있으면 실행중에 널포인터뜸) 변수이름 뒤에 !!. 명시
- 엘비스 연산자 : 변수가 null인지 검사하여 아니라면 왼쪽식을 null이라면 오른쪽식을 실행함
```
println("length : ${str?.length?:-1}")
//null이 아니면 length가, null이면 -1이 출력됨
```

- 자동 자료형 변환 안됨

자료형 변환 메서드를 사용해야함 (ex toDouble)
연산 시에는 범위가 큰 자료형으로 자동형 변환하여 연산한다.
Number 형과 같은 스마트 캐스트가 적용되는 자료형이 있다.
자료형 검사를 위해 is를 사용한다.

if(num is Int){
	return true;
	}
  • 값비교는 == 참조주소까지 비교는 ===
    참조비교는 값이달라도 참조값만 동일하면 true 값똑같아도 참조틀리면 false

코틀린 연산자

  • 논리 연산자의 왼쪽항에 따라 오른쪽항을 평가할지 하지않을지 정한다.

//비트연산자 생략

함수와 함수형 프로그래밍

- 코틀린 함수

fun sum(a:Int,b:Int):Int{		//함수 키워드 : fun 함수명 매개변수 러턴형
	var sum=a+b
    return sum
}

간략하게

fun sum(a:Int,b:Int):Int=a+b
or
fun sum(a:Int,b:Int):a+b

이렇게 생략할 수 있음

- 반환값이 없는 함수

return 문을 생략할 수 있다. 반환 자료형을 Unit으로 지정하거나 생략하면 된다.
단 생략해도 반환값이 Unit으로 추론된다. (void와 기능이 같지만

fun printSum(a:Int,b:Int):Unit{
	print("sum of $a and $b is ${a+b}")
}

- 매개변수로 디폴트값 초기화

fun add(name: String, email: String="default"){
}

- 매개변수 하나로 여러개 인자 받기 = 가변 인자

fun add(vararg counts: String){
	for(num in counts){
    	print("$num")
    }
}

fun main() {
	add(1,2,3,4)
    add(4,5,6) 
    //이렇게 둘 다 가능 
}

vararg를 매개변수 앞에 붙인다. String 형 배열로 전달된다.

- 함수 호출과 메모리


함수의 정보는 프레임이라는 정보로 스택의 높은 주소부터 채워진다
지역변수는 함수가 종료되면 스택 프레임과 함께 사라진다.

- 스택오버플로

힙영역에는 동적으로 생성된 객체의 정보가 담겨있는데 힙에서는 낮은 주소에서 높은 주소로 정보를 저장한다. 그래서 두영역이 만나지 않도록 메모리를 관리하는것이 중요하다 무한 함수호출로 스택 프레임이 정해진 스택 영역 경계를 넘어가면 스택 오버플로우가 발생한다.

함수형 프로그래밍

  • 순수함수 : 같은 인자에 대하여 항상 같은 결과를 반환하고 함수외부의 어떤 상태도 바꾸지 않는 함수
  • 람다식 : 다른 함수의 인자로 넘기는 함수, 함수의 결괏값으로 반환하는 함수, 변수에 저장하는 함수를 말한다.
    => 일급 객체의 특성을 가진 이름없는 함수
  • 일급객체
  1. 함수의 인자로 전달할 수 있다.
  2. 함수의 반환값에 사용할 수 있다.
  3. 변수에 담을 수 있다.
    를 만족하는 것.
    함수가 일급 객체면 일급함수, 일급함수에 이름이 없는 경우 람다식

고차함수

다른 함수를 인자로 사용하거나(or) 함수를 결괏값으로 반환하는 함수
=> 일급 객체 혹은 일급 함수를 서로 주고받을 수 있는 함수가 고차함수이다.

  • 일반함수를 인자나 반환값으로 사용하는 고차 함수
fun main(){
	val res1=sum(3,2)	//일반인자
    val res2=mul(sum(3,3),3) 	//인자에 함수를 사용
    println("funcFunc:${funcFunc()}")
}
fun sum(a:Int, b:Int)=a+b
fun mul(a:Int, b:Int)=a*b

fun funcFunc():Int{		//함수의 반환값으로 함수 사용
	return sum(2,2)
    }
  • 람다식을 인자나 반환값으로 사용하는 고차함수
fun main(){
	var result:Int
    val multi={x:Int,y:Int->x*y}		//일반 변수에 람다식 할당
    result=multi(10,20)		//람다식이 할당된 변수는 함수처럼 사용 가능
    println(result)
}

궁금한점 : 함수랑 뭐가다른지 ??????

val multi : (Int,Int)-> Int={x:Int,y:Int-> x*y}	//생략되지 않은 전체 표현
val multi :{x:Int, y:Int->x*y}	//선언 자료형 생략 매개변수에 자료형이 지정되어 있어 추론 가능함
val multi:(Int,Int)->Int={x,y-> x*y}
// 람다식 매개변수 자료형의 생략
// 람다식 매개변수, 선언 자료형 둘다 생략하면 추론이 불가능 하므로 오류가 발생한다.

val greet : ()-> Unit={println("Hello World"} 	//매개변수 없음 반환값 없음(Unit)

val square: (Int)->Int={x->x*x}		//매개변수가 하나만 있을 때 람다식의 자료형 생략한 것

123 람다식과 고차함수 호출하기

REFERENCE

그림 출처 : Do it! 코틀린 프로그래밍
정적언어와 동적언어
코틀린의 null처리

profile
남기고 싶은 개발자입니다 :>

0개의 댓글