본문 바로가기
5번 프로그래밍/구글 부트캠프

2일차, 안드로이드 어플 만들어보기 - 코틀린 기본 사용

by 하늘나는 곰 2020. 12. 28.

무언가 어려운 말이 막 나오기 시작합니다.

 

키워드는

 

데이터 유형

 

연산자

 

변수

 

제어구조

 

nullable

 

non-nullable

 

등등이 되나 봅니다.

 

그리고 1장에서 알려주던 Udacity에서 예에 문제를

풀으라고 지시를 해줍니다.

 

미묘하게 귀여운 수조관을 이용한다고 합니다.

 

 오늘을 시작해 봅시다.

 

아주 친절하게 프로그램부터 실행하라고 합니다.

 

이렇게까지 친절할 줄은 몰랐네요.

 

tools => Kotlin => Kotlin REPL 까지 선택을 하고 봅시다.

 

프로그램을 실행 했더니 이런에 하던 'Hello Kotlin'이 그대로있네요.

 

 

현재 활성화가 문제 없이 되는 것 같습니다.

 

굳이 새파일을 만들지 않고 그대로 진행해 보겠습니다.

 

처음 hello kotlin 했을 때와 같이 이상없이 작동을 합니다.

 

테스트 해볼 예제

 

1+1 ⇒ res8 : kotlin.Int = 2

 

53-3 ⇒ res9 : kotlin.Int = 50

 

50/10 ⇒ res10 : kotlin.Int = 5

 

1.0/2.0 ⇒ res11 : kotlin.Double = 0.5

 

2.0*3.5 ⇒ res12 : kotlin.Double = 7.0

 

구글 예시에는 이렇게 설명이 되어있습니다.

 

이것을 복붙을 하라는것이 아니라 사칙 연산이 어떻게 되는지

 

눈으로 결과를 보라는 의미 같습니다.

 

저쪽에 res 어쩌고는 결과 값입니다.

 

우리가 써봐야 할것은 그냥 그대로의 수식을 쓰시면 됩니다.

 

50/10을 쓰고 컨트롤 + 엔터를 치면,

 

결과 값으로 'res2: kotlin.Int = 5'를 보여줍니다.

 

가볍게 사칙연산 문제를 몇개 해봅시다.

 

그리고 다음은 소수점 이하 계산을 보기위해서

 

여러가지를 해보라고 합니다.

 

정수만쓰면 나누기가 0으로 떨어지지만,

 

분자든 분모든 한쪽이라도 소수점을 적으면

 

Int라는 함수에서 Double로 바뀌면서 소수점까지 계산됩니다.

 


다음은 문자까지 써보겠습니다.

한글로 하면 회(3) 이라고 써져 있길레 영문판을

 

그대로 스크린 샷으로 가져 왔습니다.

 

 

마찬가지로 아무것도 모르는 우리는 그냥 시키는대로

 

그대로 써보겠습니다.

그런데 뭐지?

 

괄호안에 3을 쓰는 순간 뭔가 수상한 other이라는 것이 떴습니다.

 

3초 당황했지만 그대로 그냥 깡으로 밀어 붙입니다.

 

무시하고 바로 '컨트롤 + 엔터' 타닥탁!

 

구글신 선생님이 원하는 결과값과 같은 것이 나왔습니다.

 

의미적으로는 2를 3번 반복해라 같습니다.

 

2.times(3) = 2x3 정도라고 마음대로 해석하고 넘어갑니다.

 

 

 

다음은 예시 문장으로는 이해가 안됐는데

 

프로그래밍을 하면 차이가 보입니다.

 

3.5.plus(4) = 3.5 + 4를 하라는 의미로 해석됩니다.

 

마지막은

 

2.4.div(2) = 2.4 / 2 정도로 해석되네요.

 

항상 여러분 실행하는 키는 컨트롤 + 엔터 입니다.

 

자연스럽게 저처럼 enter 만 누르고 왜 안되지 이러시면 안됩니다.

 

 

위의 과정이 객체인 것 처럼 호출을 한 것이라고 합니다.

 

또 무슨말인지 모르겠지만,

 

'굳이 숫자로 할 수 있는 것을

 

쓸대없이 글자처럼만들어서 계산을 할 수 있다.' 라고

 

해석을 해봅시다.

 

전문용어로 boxing 이라고 하는 것 같습니다.

 

근데 메모리가 많이 사용되니 쓸대없이 쓰지말라고 하네요.

 

저는 초보자이니 쓰지말라고 하면 그냥 쓰지않겠습니다.

 

어렵게 생각하지 맙시다.

 

우리는 지금 사용법을 익혀서 빠르게 어플을 만드는 것이 목적입니다.

 

일단 어려운 단어는 넘어 가겠습니다.

 


어려운 말은 일단 넘어가려고 했는데,

 

하... 산넘어 산입니다.

 

이제부터 변수를 만들어서 직접 확인해 보는 작업을 할 것입니다.

 

한번쯤은 들어 봤던 x=1 이라고 할때,

 

x 라는 변수(미지수)에 '1' 이라는 뜻을 지정한다는 겁니다.

 

 

요구하는 것을 그대로 쳐봅시다.

 

자 여기서 중요한 점!

 

Int 같이 내장되어 있는 명령을 할 때는 대문자 / 소문자를 정확하게 해야합니다.

 

int 라고 칠 때와

 

Int 라고 칠 때는 인식의 차이가 전혀 다릅니다.

 

val i : Int = 6 => 컨트롤 +엔터 => i => 컨트롤 +엔터 까지해서

 

i의 안에는 6이라는 것이 들어가 있음이 보입니다.

 

Int라는 것만 사용하지 않고 유형을 바꿔 보는 것이 다음 목표입니다.

 

변하게 해주기 위해서는 .to까지 글을 작성했을 때,

 

바꿀 수 있는 리스트를 친절하게 보여줍니다.

 

기존 프로그램은 Byte니 Double니 일일이 외워서 타자를 치는 것을

 

.to 를 이용하여 빨리 찾아갈 수 있게 한 것을 자랑하고 싶은가 봅니다.

 

 

많은 리스트 중에 무슨 차이인지 모르겠어서

 

가장 위에 있는 Byte로 변경을 하고

 

시키는대로

 

println을 사용하여 실행까지 해보았습니다.

 

도대체 무슨차이지? 갸웃 해집니다.

 

혹시나 싶어서 다시 i에 Int=6을 주고 변경해 보았습니다.

 

내부적인 유형은 바뀌었는데,

 

우리 눈에 보이는 것은 똑같네요.

 


Int / Byte / String / Double 등등 일단 수의 유형이라고 번역이 되니

 

이하 수의 유형이라고 하겠습니다.

 

예제는

 

b2에 Byte라는 수의 유형을 선택하여 1 이라는 명령을 주었습니다.

 

 

i1에 b2를 Int로 수의 유형을 바꾸고 싶지만,

 

Int는 Byte와 같지 않으니 에러!


i2에 b2를 String로 수의 유형을 바꾸고 싶지만,

 

String은 Byte와 같지 않으니 에러!


i3에 b2를 Double로 수의 유형을 바꾸고 싶지만,

 

Double는 Byte와 같지 않으니 에러!


라고 뜨는 것을 보여줍니다.

 

실제로 전부다 한번 처 보았습니다.

 

똑같이 경고 창이 뜹니다.

 

요는 수의 유형을 변경을 하고 싶을 때는,

 

Int = b2 처럼 강제로 지정 변환을 시켜주지 말고 .to를 이용하라는 것 같습니다.

 

수의 유형을 바꾸고 싶을 때는 .to를 이용할 것!

 

똑같이 따라서 한번 쳐보기전에 키설명

 

요렇게 .to를 쳤을때 사용가능한 리스트 들이 다 뜹니다.

 

이것을 타자연습한다고 생각하고 그대로 따라 치는 것도 좋지만~

 

오타가 발생하는 것을 줄이기 위한 방법으로

 

키보드 방향키를 이용하여 내가 원하는 것을 선택하고 엔터 & TAP키를 누르면

 

해당 하는 것이 써집니다.

 

그리고 여러분 이렇게 한번에 예시문장을 쓰면 실행이 되지 않습니다.

 

결과 값이 맨 마지막 것만 보여줍니다.

 

하나씩 하나씩 확인을 해보시길 바랍니다.

 


긴 상수 숫자 끊기

 

우리는 숫자를 끊어서 쓸 때 3자리에서 ','을 사용합니다.

 

1000을 보기 쉽게 1,000을 하듯이 말입니다.

 

코틀린에서는 끊어서 표시하기 위해서 ' _ '를 사용합니다.

 


사용 하는 변수 유형의 차이

 

val / var 의 차이

 

val = Value = 값 / var =Variable = 변하기 쉬운

 

이라는 뜻을 일단 알고 진행해 보겠습니다.

 

영어 공부를 해야겠다는 생각이 또 들기 시작합니다.

 

미지수 변수를 지정할 때, 프로그래밍 도중

 

val로 한번 지정을 한 것은 값이 변하지 않고

 

var로 한번 지정한 것은 값을 변화 할 수 있다는 뜻같습니다.

 

무슨 말일까요?

 

어디 한번 해보겠습니다.

 

var =Variable = 변하기 쉬운 사용해 보겠습니다.

 

1. 처음 'fish' 라는 변수에 1의 값을 집어 넣습니다.

 

2. 'fish' 라는 변수에 2로 집어 넣습니다.

 

3. 'fish' 라는 값을 출력합니다.

 

결과 'fish' 값은 2로 바뀌었음을 알 수 있습니다.


val = Value = 값 을 사용해 보겠습니다.

 

1. 처음 'fish' 라는 변수에 1의 값을 집어 넣습니다.

 

2. 'fish' 라는 변수에 2로 집어 넣습니다.

 

3. 'fish' 라는 값을 출력합니다.

 

결과는 에러가 뜹니다.

 

reassign = 재배치하다

be reassigned 는 수동태로 변하면서 재배치 당하다.

정도로 되겠네요.

 

val은 fish=2로 재배치 할 수 없다면서 에러가 뜹니다.

 


그럼 var =Variable = 변하기 쉬운 함수는 만능일까?

 

그렇지도 않습니다.

 

 

구...구글 신님 조금만 더 설명을 해주세요!!

 

『대답이 없다. 구글신님은(는) 죽었나보다.』

 

그럼 구글신님은 저쪽으로 치워두고~

 

강행 돌파해 보겠습니다.

 

요번건 일단 똑같이 쳐 보았습니다.

 

여기까지는 계산대로 완벽합니다.

 

'저기의 마지막 말 수의 유형을 변경할 수 없습니다.'를 주목해서

 

'fish'의 수의 유형을 바꿔보겠습니다.

 

영어가 너무 길어서 이번에는 해석이 안됩니다.

 

error: the floating-point literal does not conform to the expected type Int

 

literal : [형용사]정확한(=accurate, exact, precise, right, true, literal)



컴퓨터에서는 '고정된 값' 정도의 의미랍니다.



conform to : ~따르다



expected : [형용사] 예상되는



the floating-point literal / does not / conform to / the expected type Int



정확한 floating point는 예상된는 Int 타입에 따르지 않습니다.



Int 타입이 아니라는 뜻이겠네요.

 

『'fish'에 처음 정수의 유형인 Int를 주면, 소수점의 유형인 Double로 자동으로 받지 못한다.』

 

공부가 되는 것 같습니다.

 

 

한번에 쭉 같은 상황으로 다시 한번 보겠습니다.

 

 

var / val 에서 사용한 예제를 그대로 사용하겠습니다.

 

결과는?

 

 

이미 봤던 것 처럼 2로 변경이 되었습니다.

 

그럼 이건?

 

프로그램 도중 2.5로 바꾸는게 지시해 보겠습니다.

 

예상되는 결과가 어떤가요?

 

정답은~ 두구두구두구

 

 

바뀌지 않습니다.

 

var도 그렇게 만능하지 않다는 것을 기억해 둡시다.

 


변수 보간

 

우선 한국말부터 못알아 듣겠습니다. 통째로 구글신님의 가르침을 먼저 봅시다.

 

 

와하하하하하하하. 무슨 말인지 전혀 모르겠습니다.

 

 

variable interpolation 영문판에서는 이렇게 되어있습니다.

 

그럼 도와줘요.

 

위키 할아버지~

 

 

수학시간에 한번은 들어봤던 내용입니다.

 

중간의 한 정보를 주어서 좀 더 정밀하게 보정을 한다.

 

뉘양스로만 우선 이해를 합시다.

 

그리고 우리는 실전으로 비교해 볼꺼에요.

 

val numberOfFish = 5
val numberOfPlants = 12
"I have $numberOfFish fish" + " and $numberOfPlants plants"

 

예시의 글을 그대로 써봅시다.

 

이부분은 타자가 길어서 오타가 많이 납니다.

 

그냥 붙여넣기를 하는게 정신건강에 좋습니다.

 

 

$표시를 한 명령어에 숫자가 삽입이 되면서

 

문장 + 숫자의 조합으로 출력이 되었습니다.

 

띄어쓰기가 안되있는게 좀 아쉽네요.


그럼 $ 표시를 지워보겠습니다.

 

위와 벌써 차이가 납니다.

 

$표시가 있을 때는 변수자체로 인식을 했는지 '하얀색 글자로' 표기 되는데

 

$표시가 없을 때는 그냥 글자로 인식을 한 것 같습니다. 전부 '초록색'으로 표기됩니다.

 

실행해 보겠습니다.

 

 

전부다 '글자'로 인식을 하고 결과값으로 전부다 '글자'를 출력합니다.

 

글자로 출력하는 것을 보정(=보간)하기 위해 ' $ ' 를 사용하는 것을

 

알려주려고한 것 같습니다.


다음은 중괄호 예시를 사용해보겠습니다.

 

"I have ${numberOfFish + numberOfPlants} fish and plants"

 

복사 붙여 넣기를 하면 ' + ' 까지가 숫자로 인식이 된 듯 합니다.

 

계산기 처럼 숫자에 사칙연산까지 적용된 것 처럼 보이는데요.

 

실행 해보겠습니다.

 

 

5+12가 통째로 계산이 된 후 결과값 17로 종료 된 것이

 

삽입되어 출력을 시킵니다.

 

' $ ' 를 이용한 변수 보간이 무슨 말인지 저는 보였습니다.

 

여러분은 어떻습니까?

 

근데 저는 중괄호를 참 싫어합니다.

 

손으로 그림 그리기가 안이뻐서 수학시간에서 ' (( ' 같은

 

느낌을 쓰는 것을 더 좋아 했습니다.

 

그런 의미에서 '( '로 해보겠습니다.

 

 

 

 

부~울편 합니다.

전부다 글자로 인식을 하고 출력을 하네요.

 

' $ ' 와 ' {} '의 조합을 기억합시다.


잠시 후 이제부터 스트레스 만땅으로 받고

 

제일 중요한

 

논리와 조건의 시간입니다.

 

이부분은 별도의 설명보다 예제로만 나와있고

 

결과값이 나왔는지 읽고 보라는 것 같습니다.

 

 

if = 만약 ~ 라면 / else = 다 틀렸다면

 

정도의 의미로 해석을 하면됩니다.

 

if / else 등을 논리 함수라고 하고,

 

~ 부분이 우리가 원하는 조건문이 들어 갑니다.

 

val numberOfFish = 50
val numberOfPlants = 23
if (numberOfFish > numberOfPlants) {
    println("Good ratio!") 
} else {
    println("Unhealthy ratio")
}

{}의 위치와 오타에 주의하면서 작성해봅시다.

 

Unhealthy = 건강하지 못한 / ratio = 비율

 

똑같이 따라하면 약간 질리니깐 중간중간 멘트 정도는

 

그때그때 기분에 따라 바꿔봅시다.

 

결과를 볼까요?

 

와우 글자를 토해내지 못합니다!

 

놀라운 사실을 알았습니다.

 

한글을 인식하지 못하는 건가요?

 

여러분 오타에 항상 주의하세요!

 

저는 3번이나 수정한 끝에 출력을 했는데,

 

글자가 깨졌습니다.

 

한글을 인식을 못하는 것 같으니 영어로 바꿔주겠습니다.

 

됐습니다. 휴 출력이 되네요.

 

해석을 해봅시다.

 

1. numverofFish 에 50의 값을 넣으세요.

 

2. numverofPlants 에 23의 값을 넣으세요.

 

3. 만약 'numverofFish'가 'numverofPlants'보다 크다면

"good ratio"를 출력하세요.

 

4. if의 조건이 틀렸으면, "bad ratio"를 출력하세요.


반대로 50과 23의 값을 바꿔보겠습니다.

 

예상한 대로 bad ratio가 출력이 됩니다.

 

if (조건문){요청} else(조건문){요청}의 순서로

 

작성을 하면 될 것 같습니다.

 


if의 범위를 위한 작성이라는데 이것도

 

보기만 해서는 무슨말인지 모르겠습니다.

 

작성 후 이것저것 바꿔보겠습니다.

 

val fish = 50
if (fish in 1..100) {
    println(fish)
}

1..100이 알아보기 힘듭니다.

 

띄어쓰기 없이 그냥 ..을 치시면되는데 알아보기가 힘드네요.

 

출력되는 값은 결과가 같이 나왔습니다.

 

해석을 해보겠습니다.

 

1. 'fish'에 50의 값을 넣으세요.

 

2. 만약 'fish'가 1~100 안에 있으면

 

3. 'fish'를 출력하세요.

 

그럼 여기서 fish의 값을 바꿔보는 것과 1..100의 범위를 바꿔보겠습니다.

 

fish = 101로 해보겠습니다.

 

한참을 지나도 fish가 출력이 되지 않습니다.

 

100의 밖에 있기 때문에 조건을 충족시키 못했기 때문입니다.

 

다음 fish = 99.9 소수로 해보겠습니다.

 

에러가 뜹니다.

 

이부분은 해석하기 힘드니

 

구글 번역기 선생님께 도움을 받아 봅시다.

 

using 'contains(Double): Boolean' is an error. This `contains` operation mixing integer and floating point arguments has ambiguous semantics and is going to be removed.

 

='contains (Double) : Boolean'사용은 오류입니다. 정수와 부동 소수점 인수를 혼합하는이`contains` 연산은 모호한 의미를 가지며 제거 될 것입니다.

 

정수와 소수점이 혼합이 되면 연산이 모호해 지기 때문에

 

에러로 인식을 한다는 것 같습니다.


그럼 다음 테스트를 해야죠

 

fish=2 / 범위를 3..10 까지로 해보겠습니다.

 

여기까지는 마찬가지로 범위 밖이니 출력이 안되는 것 같습니다.

 

사이값을 1~10 까지를 프로그램에서는

 

1..10으로 표현을 하면 됩니다.


그럼 다음 fish = 6 / 범위를 1.0~10.0으로 소수로 해보겠습니다.

 

 

위와 같은 똑같은 에러가 뜹니다.


마지막 테스트 fish = 6.0 / 범위도 1.0 ~ 10.0 전부 소수로 해보겠습니다.

 

논리 연산자를 사용하기 위해서는

 

수의 영역을 맞춰야 한다는 것이 밝혀 졌습니다.

 

정수는 정수 / 소수는 소수로만 사용이 가능

 

기억해 둡니다.

 


이건 또 전혀 알아 먹을 수 없네요.

 

'==' 의 부위에 '&&'와 '\\'을 사용하라는 것 같은데

 

이것도 마찬가지로 맨땅에 해딩 해봅시다.

 

'else if' 는 'if'와 'else'의 사이에 들어가는 논리 함수입니다.

 

'if = 만약 ~ 하다면' 에서 옳다=turn / 그르다=false 를 구분하게 됩니다.

 

옳을 때는 그냥 출력하면 되는데, 그르다=false 일 때,

 

한번더 질문을 던져주기 위해 사용합니다.

 

'else if = 그르다면 ~' 하면서 한번더 옳다=turn / 그르다=false 를 물어볼 수 있습니다.

 

그리고 최종적으로 끝내기위해

 

'else = 전부 다 그르다면'으로 해석을 하도록 합시다.

 

if (numberOfFish == 0) {
    println("Empty tank")
} else if (numberOfFish < 40) {
    println("Got fish!")
} else {
    println("That's a lot of fish!")
}

그대로 복사 붙여 넣기를 했는데 오류가 뜹니다.

 

결과로써 원하던 것은 That's a lot of fish! 가 출력이 되야하는데 말입니다.

 

이 문장에서 문제점은 numberOfFish를 처음에 정의를 하지 않았습니다.

 

지금 문장을 그대로 해석을 해보겠습니다.

 

1. 만약 'numberOfFish'가 0과 같다면,

"Empty tank"를 출력하시오.

 

2. 그렇지 않다면, 'numberOfFish'가 40보다 작은지 보시오.

작다면 "Got fish!"를 출력하시오.

 

3. 다 틀렸다면, "That's a lot of fish!"를 출력하시오.

 

입니다.

 

우선 구글신 선생님은 "That's a lot of fish!"를 출력하고 싶으신가 보니

 

우리가 미지수를 먼저 제시를 해줍시다.

 

if / else if를 전부 그르다로 해주어야합니다.

 

대충 40이상의 숫자를 넣으면 되겠네요.

 

numberOfFish에 41을 써줍시다.

 

 

이번건 구글 선생님의 실수로 먼저 해석을 하게 되면서

 

역순으로 고칠 것이 없게 해버렸습니다.

 

val numberOfFish = 41
if (numberOfFish == 0) { 
    println("Empty tank") 
} else if (numberOfFish < 40) { 
    println("Got fish!") 
} else { 
    println("That's a lot of fish!") 
}

이 맞는 문장이 되겠습니다.

 

자 그럼 나머지 if 와 else if 를 출력하기 위해서

 

변수 "numberOfFish"를 0 과 39로 수정을 빠르게 해봅시다.

 

여기는 예상대로 if 문에서 출력이 되었습니다.

 

이쪽도 무난하게 if 문을 통과하고 else if 문에서 걸립니다.

 

먼저 미지수를 지정해 주는 것이 얼마나 중요한지 배우게 되었습니다.

 


* 잠시 쉬어가기 타임 Kotlin 한글 깨짐 수정하기 *

 

위쪽의 예시와 같이 한글의 글자가 깨지는 분들이 있을 겁니다.

 

이것을 한번 수정을하고 들어갑니다.

 

Help => Edit Custom VM Options...를 치게 되면

 

위와 같이 idea64.exe.vmoptions 이란 것이 열립니다.

 

이곳의 맨 아래쪽에

 

-Dfile.encoding=UTF-8

 

그대로 복사 붙여넣기 해주세요.

 

그다음 컨트롤 + S를 해서 저장 후 프로그램 재실행


File => Settings 선택합니다.

 

왼쪽 리스트에서 Editor => File Encodings를 들어가

 

붉은 박스에 있는 부분들을 전부 UTF-8로 수정 후 옆에 체크박스 체크!

 

OK를 합니다.

 

간신히 한글 출력까지 완료 했습니다.

 

휴~


처음 들어보는 when 함수 입니다.

 

when이라는 것이 코틀린의 좋은 기능 중 하나라고 합니다.

 

if 조건문을 보면 else if를 계속 붙이면서 문장이 길어지는 것을

 

if / else if라는 문자를 쓰지 않고 조건문만 바로

 

쓰기위해 만들어진 기능으로 알면 되겠습니다.

 

val numberOfFish = 50
when (numberOfFish) {
    0  -> println("Empty tank")
    in 1..39 -> println("Got fish!")
    else -> println("That's a lot of fish!")
}

만약을 위해 약간 수정해

 

'numberOfFish' 에 50이라는 값을 주고 시작해 보겠습니다.

 

해석의 시간 빠밤

 

1. 'numberOfFish'에 50의 값을 넣습니다.

 

2. 'numberOfFish'라는 녀석이 보입니까?

 

3. 0이냐? "Empty tank"를 출력해라.

 

4. (아니면) 1초과 39미만이냐? "Got fish!"를 출력해라.

 

5. 전부 아니냐? "That's a lot of fish!"를 출력해라.

 

정도의 해석이라고 보면 될 것 같습니다.

 

시각적으로 정리를 시키는게 목적인 것 같습니다.

 

->를 쓰는게 신선합니다.

 

프로그램이 머리가 많이 좋네요.

 

근데 switch는 어디에 쓰는지 모르겠습니다.

 

큰일이네요.

 

switch 뭔지 알아오기! (숙제)

 

모르는 것은 일단 넘어 갑시다.


nullable / non-nullable 변수의 차이 알아보기

 

nullable은 처음 들어보는데 이게 뭔가요?

 

Nullable 형식 - Null (비어있는) + able (~ 될 수 있는), 즉 "비어 있는 상태가 될 수 있는" 형식

 

한국어로 봐도 무슨 말인지 모르겠습니다.

 

이정도로 써놓은 것을 보니 어지간히 프로그래머들을

 

골탕 먹이는 녀석인가 봅니다 집중해 봅시다.

 

혹시나 모를 번역 오류로 영문과 한글번역을 다 가지고 왔습니다.

 

근데 솔찍히 봐도 모르겠습니다.

 

해석을 대충 해보면 수의 유형 Int에 빈공간 null은 들어갈 수 없다!

 

이것을 '?'를 사용해서 'Int?' 상태가 되면 빈공간 null을 받아 들일 수 있다!

 

읽어보면 그렇게 해석이 되네요.

 

한쪽만 미지수 상태로 만들지 말고 그럴 바에는 양쪽다

 

확정을 하지말고 여유롭게 '그럴껄?' 상태로 두자는 것 같습니다.

 

실제로 실행해 보겠습니다.

 

var rocks: Int = null

당연히 안되네요.

 

 

var marbles: Int? = null

그럼 '?'를 적용하고 투입해 보겠습니다.

무슨 값을 적용한 것이 아니라 출력이 되는 결과값이 없지만,

 

적어도 에러는 뜨지 않습니다.

 

그럼 Double? String?은 먹힐까요?

 

 전부다 저항없이 받아 들입니다.

 

뭐가 와도 받아 들일 준비가 되어서 Come! Come! 하고 있는

 

대기 상태겠지만, 쓰는 입장에서는

 

손 놓고 놀고 있는건 아닐지 불안하기도 하네요.


와......전혀 무슨말인지 모르겠네요.

 

일단 갈겨서 쳐봅시다.

 

우리는 눈으로 보고 현상과 비교해서 상황파악을 해야겠습다.

 

1번 상황문

var fishFoodTreats =6
if (fishFoodTreats != null){
   fishFoodTreats = fishFoodTreats.dec()
}
println(fishFoodTreats)

' != '의 의미는 '같지 않다.' 입니다.

if 문 다음에는 else가 항상 와야하는데 그 위치도 중요한가봅니다.

 

비어있는 곳이면 괜찮은데 }가 끝난 위치에 else이외에 것을 쓰면 에러가 뜹니다.

 

주의합시다.

 

한 줄 띄우고 쓴 println 문은 이상이 없고

 

반대로 }를 위로 올린 상태에서

 

줄바꿈을 하면 println이 저항이 없이 써집니다.

 

if 문 ' {} ' 는 많이 예민한 친구인 것 같습니다.

 

그리고 .dec()는 -1을 명령하는 것같습니다.

 

'fishFoodTreats.dec()' = 'fishFoodTreats' -1

 

()안에는 어떤 숫자를 집어넣어도 에러가 뜨네요.

 

.des() = -1 로 생각을 우선 합니다.

 

해석을 하자면,

 

1. 'fishFoodTreats'에 6을 집어넣어라.

 

2. 'fishFoodTreats'은 null이 아니다! 맞으면,

'fishFoodTreats' -1 을 'fishFoodTreats'에 집어 넣어라.

 

3. 'fishFoodTreats'을 출력하라.

 

몇가지 숫자를 적용해 보니 맞는 것 같습니다.


2번 상황문

var fishFoodTreats =6
fishFoodTreats =fishFoodTreats?.dec()
println(fishFoodTreats)

직접 해보면 이런 결과가 나옵니다.

 

' ? '의 의미가 중요하겠네요.

 

지금은 ' null '의 시간이니깐 'fishFoodTreats' =null을 집어 넣어봅시다.

var fishFoodTreats = null
fishFoodTreats 
= fishFoodTreats?.dec()

가만 생각하니깐 당연히 빈 공간이니깐

 

뭐가 되도 진행이 안되겠네요.

 

아!

위에 있는 문장을 그대로 줄인거구나!!!

 

한숨 자고 오니깐 뭔가 보였습니다.

 

보시면 1번 상황문과 2번 상황문의

 

'fishFoodTreats'의 값이 같고

 

.dec() 까지도 같은데 같은 값이 나옵니다.

 

다른 점 하나만 꼽자면

 

'fishFoodTreats?' = '(if의 조건문) 'fishFoodTreats' != null'

 

이부분이 보이네요.

 

한국어로 수정을 하면

 

'fishFoodTreats?' = 'fishFoodTreats'는 null이 아니다.

 

'?'는 'null이 아니다.' 라는 것을 보여주는 것이었습니다!

 

한참 고민했네!


3번 상황문

var fishFoodTreats =6
fishFoodTreats = fishFoodTreats?.dec() ?: 0
println(fishFoodTreats)

2번 상황문과 똑같은 출력값이 나옵니다.

 

' ? : 0 '의 명령어를 어떻게 해석을 해야할까요.

 

구글 신님께서는 ' ? : 0 ' 이 웃는 얼굴과 같은

 

'Elvis operator' 엘비스 연산자라고 하는 것을 쓰게 하고 싶으신 것 같습니다.

 

"뒤쪽에 있는 그렇지 않으면 뒤에 있는 값 ( ? : 0 )을 사용하십시오."을

 

해석을 해야할 텐데 무슨 말인지 모르겠습니다.

 

3번 상황문 변경

var fishFoodTreats: Int? = null
 fishFoodTreats = fishFoodTreats?.dec() ?: 0
 println(fishFoodTreats)

하고자 하는건 'fishFoodTreats' = 'null' 형태로 만들어줘서

 

'0'을 사용하게 만들어줘야합니다.

 

몇가지 상황문을 변경한 끝에 통하는 것을 찾은것이 저것입니다.

 

 

응용은 아직 전혀 되지 않습니다.

 

다시 위쪽부터 읽어가면서 똑같은 것을 상용해보았습니다.

 

'수의 유형? = null' 의 형태를 사용해야 실행이 됩니다.

 

미지수? = null은 인식을 하지 못합니다.

 

' 미지수 : (수의 유형)? = null' 이 ' 미지수 = null '을 지정할 수 있는 방법입니다.

 

30분 걸렸네요. 꼭 기억합시다.


null 설명은 전부 다 설명만으로는

 

읽어도 모르는게 끔찍합니다.

 

나중에 실전에서 허우적 할께 눈에 선하네요.

 

오지도 않은 미래는 재끼고!

 

그냥 쭉쭉 나가보자!

 

 

키워드는

 

널 포인터 예외 = nullPointerExceptions

 

뱅 = bang = !

 

더블뱅 = double-bang = !! = null이 아닌 단언 연산자

 

단, 일반적으로 더블 뱅 연산자를 사용하는 것은 좋지 않은 것.

 

대충 느낌으로는 위에서 했던

 

『var fishFoodTreats: Int? = null』 을 한번에 만들기 위한게 '!!' 같습니다.

 

모르겠으니 어디 상황문을 그대로 써보겠습니다.

 

상황문

val len = s!!.length   // throws NullPointerException if s is null
println(len)

무시무시한 에러 폭풍을 볼 수 있습니다.

 

흠... ' 모든값을 null이 아닌 유형으로 변환한다. '

 

이 말은 결국은 'null이 아니다.' 라고 해석해야겠죠?

 

그러면...

 

3번 상황문을 가지고 와서 바꿔보겠습니다.

 

3번 상황문

var fishFoodTreats: Int? = null 
 fishFoodTreats = fishFoodTreats?.dec() ?: 0 
 println(fishFoodTreats)

3번 상황문을 해석해 보겠습니다.

 

1. ' fishFoodTreats' 는 null 로 만들어라

 

2. ' fishFoodTreats '가 null이 아니면 -1을 계산해서 ' fishFoodTreats '에 집어 넣고,

null이면 0을 투입하고 ' fishFoodTreats '에 집어 넣어라.

 

3. ' fishFoodTreats'를 출력하라.

 

여기서 '!!' 더블뱅을 사용해 보겠습니다.

 

3'번 상황문

var fishFoodTreats: Int? = null  
 fishFoodTreats = fishFoodTreats!!.dec()   
 println(fishFoodTreats)

드디어 뭔가 비슷한게 보이기 시작했습니다.

 

변형된 3번 상황문을 다시 해석해 보겠습니다.

 

1. ' fishFoodTreats' 는 null 로 만들어라

 

2. ' fishFoodTreats '는 'null이 아니다.' -1을 해서,

' fishFoodTreats '에 집어넣어라

 

3. ' fishFoodTreats '를 출력하라.

 

해석은 했는데 말이 더 꼬여보이네요.

 

3''번 상황문

var fishFoodTreats: Int? = 3    
 fishFoodTreats = fishFoodTreats!!.dec()   
 println(fishFoodTreats)

' fishFoodTreats '에 값을 집어 넣으면 어떻게 될까요?

 

'null이 아니다.' 에서 ' 3 ' 이 투입이 되는 것 같습니다.

 

3 -1 까지 적용이 되서 ' 2 ' 를 출력하는 것 같습니다.

 

이부분도 나중에 실전에서 고생하게 될 것 같습니다.


실전에서 많이 쓰게 되는 반복문의 시간입니다.

 

여기부터는 머리속에서 암산을 잘 하던지

 

연습장을 옆에 펼쳐 놓고 계산을 해야겠습니다.

 

 총 3단계로 설명을 해줍니다.

 

1단계 : 목록 만들기

 

예제를 그대로 써보고 눈으로 보는 게 좋을 것 같습니다.

 

1번 상황문

val school = listOf("mackerel", "trout", "halibut")
println(school)

mackerel = 고등어

 

trout = 송어

 

halibut = 넙치

 

출력도 이상없이 됩니다.

 

해석을 해보겠습니다.

 

1. ' school '에 리스트를 만든다, 리스트는 "고등어", "송어", "넙치" 이다.

 

2. ' school '을 출력하시오.

 

여기까지는 크게 무언가 문제는 없어보입니다.

 

바로 2번 상황문을 가져와 보겠습니다.

 

2번 상황문

val myList = mutableListOf("tuna","salmon","shark")
myList. remove("shark")
println(myList)

리스트의 목록을 삭제하는 연습입니다.

 

구글신님의 예제는 println 명령이 없습니다.

 

구글신님은 안정적으로 제거가 된다면,

 

'true' 로 전달이 되는 것을 보여 주고 싶었습니다.

 

근데 우리는 눈으로 봐야하니깐, 이렇게 보겠습니다.


2 단계 : 에레이 생성

 

일종의 규격을 정하는 것을 보면 되겠습니다.

 

단, 목록과는 다르게, 한번 생성을 하면 크기가 고정 된다고 합니다.

 

목록처럼 삭제를 할 수 없다고 합니다.

 

상황문을 보겠습니다.

 

1번 상황문

val school = arrayOf("shark","salmon","minnow")
println(java.util.Arrays.toString(school))

java.util.Arrays.toString() 라는 함수를 써보라고 알려줍니다.

 

뭔지 고민은 나중에 하고 우선 실행해 봅시다.

 

여기까지는 목록과 차이를 느낄 수가 없습니다.

 

2번 상황문

val mix = arrayOf("fish", 2)
println(java.util.Arrays.toString(mix))

2번 상황문은 arrayOf에 'fish'와 숫자 '2' 라는 것을 섞어서 써보자는 것입니다.

 

구글신님의 상황문 2번을 바꿔보겠습니다.

 

수의 유형에서 'fish'는 String 타입, '2'는 Int 타입이었는데

 

문자와 숫자가 다 써지네요.

 

구글신님 출력명령까지 좀 다 써주세요.

 

너무 힘들잖아요. 흑흑

 

3번 상황문

val numbers = intArrayOf(1,2,3)
println(java.util.Arrays.toString(numbers))

 3번 상황문은 Int를 사용한 정수배열을 하기 위한 것 같습니다.

 

정수만 쓰도록

 

출력도 무난 하네요.

 

위에서 null의 복잡한 것만 보다가 갑자기

 

편하게 눈에 보이니깐 문장이 길어지더라도

 

마음이 편해집니다.

 

 

배열들을 합치는게 가능하다는 설명인 것 같습니다.

 

하나씩 바로 실행해 보겠습니다.

 

4번 상황문

val numbers = intArrayOf(1,2,3)
val numbers3 = intArrayOf(4,5,6)
val foo2 = numbers3 + numbers
println(java.util.Arrays.toString(foo2))
println(foo2[5])

여러분 훼이크가 있습니다.

 

number3 이 먼저 써져있기 때문에 4, 5, 6이 앞으로 왔습니다.

 

1, 2, 3, 4, 5, 6 순서가 아니라고 저처럼 쫄지 마세요.

 

그리고 배열의 시작의 번호가 좀 다른 것 같습니다.

 

일반적 순서 -> 1번자리, 2번자리, 3번자리, 4번자리, 5번자리, 6번자리

 

우리는 순서를 매길때 1번자리 라고 합니다.

 

하지만 컴퓨터에서는 읽은게 0번자리 부터 시작입니다.

 

컴퓨터 순서 -> 0번자리, 1번자리, 2번자리, 3번자리, 4번자리, 5번자리

 

출력되는 위치가 다른게 보입니다.

 

 

중첩 부분은 설명이 어려워 보입니다.

 

이게 예제 문제도 이상해 보이는데...

 

이건 따로 건들지 말고 그냥 바로 상황문과 결과만 보겠습니다.

 

5번 상황문

val numbers = intArrayOf(1, 2, 3)
val oceans = listOf("Atlantic", "Pacific")
val oddList = listOf(numbers, oceans, "salmon")
println(oddList)

출력이 되긴하는데, 출력문에 ' ] ' 한개가 부족하네요.

 

글자가 깨지는 부분이 뭔가 수상해서 '그냥 이런게 있다더라' 만 보겠습니다.

 

하고 싶은 말은 이것 이었나 봅니다. 맨 처음 1, 2, 3이

 

내용으로써 기능을 한게 아니라 주소의 기능으로 그 다음 것들이

 

들어올 수 있게 되었나 봅니다.


6번 상황에서는 배열 내용은 0으로 초기화를 하고,

 

그내용을 코드로 만드는 연습같습니다.

 

6번 상황문

val array = Array (5) { it * 2 }
println(java.util.Arrays.toString(array))

어레이에 (5) 부분에 자동적으로 사이즈라고 알려주네요.

 

it = iterator 라는 녀석으로 배열로 만들어진 5칸에 곱하기 2라는

 

반복된 명령을 준다는 것 같습니다.


3단계 : 루프만들기

 

본격적으로 목록과 배열의 요소를 반복하는 작업입니다.

 

'for'을 사용하라고 하고는 뭔지 설명을 안해줍니다.

 

너무하신 구글신님...

 

돌격!!!

 

1번 상황문

val school = arrayOf("shark", "salmon", "minnow")
for (element in school) {
    print(element + " ")
}

 

배열의 내용을 출력하기 위해서는

 

java.util.Arrays.toString()을 써야 했는데,

 

'for'문에 'element'로 하나씩 정리가 되서

 

출력하는 것으로바뀌었나 봅니다.

 

통째로 school의 요소가 뙁! 하고 나온게 아니라

 

shark 꺼내고, salmon 꺼내고, minnow 꺼내고,

 

출력문에 보면 ' , ' 표시가 없는게 눈에 띄입니다.

 

여기까지는 오케이 알겠어

 

2번 상황에서는 위치와, 값을 동시에 알 수 있게 해주려고 하나봅니다.

 

/n을 하면 줄바꾸기가 되고,

 

$표시를 하면 해당하는 데이터를 받겠다는 겁니다.

 

2번 상황문

for ((index, element) in school.withIndex()) {
    println("Item at $index is $element\n")
}

 

index로 몇번 째 순서인지, element로 요소를 보여줍니다.

 

휴.. 문장이 슬슬 길어지네요.

 

index를 쓰기 위해서 .withIndex()를 써야하는 것도 잊지 맙시다.

 

'for'문의 응용입니다.

 

숫자 뿐만 아니라, 글자도 출력이 되네요.

 

3번 상황문

for (i in 1..5) print(i)


for (i in 5 downTo 1) print(i)


for (i in 3..6 step 2) print(i)


for (i in 'd'..'g') print (i)

실행을 해볼 때는 한줄씩 해야합니다.

 

이렇게 되는 수가 있습니다.

 

downTo, step, .. 전부 신기하게요.

 

4번 상황에서는 whlie / do ~ whlie / ++ / -- 등을 써야하네요.

 

근데 설명은 하나도 없냐!!

 

이건 좀 너무 했다!

 

그냥 바로 복붙해 봅시다.

 

4번 상황문

var bubbles = 0
while (bubbles < 50) {
    bubbles++
}
println("$bubbles bubbles in the water\n")

do {
    bubbles--
} while (bubbles > 50)
println("$bubbles bubbles in the water\n")

repeat(2) {
     println("A fish is swimming")
}

하 참 그래 결과는 좋다 이거야.

 

근데 뭔지 해석이 안되잖아!!

 

별도로 찾아 와야 했습니다.

 

'whlie' 문은 조건이 참이 될 때 까지 반복하라. = 조건이 만족 할 때까지 반복

 

'++' = +1을 해라

 

'do whlie' = 일단 실행을 하고 조건을 본다

 

'--' = -1을 해라

 

'repeat(숫자)' = 숫자 만큼 반복해라

 

 

댓글