Kotlin 무작정 따라해보기 3일차 - Variables, Null Safety, Classes
Written by munilive on (Updated: )3일차 시작하기 - Variables, Null Safety, Classes
지난 2일차에 이어서 Learn Kotlin by Example > Introduction
의 Variables, Null Safety, Classes
에 대한 학습을 시작 합니다.
Variables
코틀린에서는 강력한 타입 추론을 지원하기 때문에 명시적인 타입을 지정 가능하지만, 타입을 지정하지 않아도 사용이 가능하다.(Typescript 처럼 타입을 지정해도 되고, 안해도 되고)
일반적으로 컴파일러가 타입을 유추해서 사용하도록 하는 편이다.(권장이라기 보다는 타입을 지정하지 않아도 상관 없으니 매번 입력할 필요가 없다라는 뜻인듯.)
변수는 mutable
변수(값을 변경 할 수 있는, Javascript let
), immutable
변수(값을 변경 할 수 없는, Javascript const
)가 있는데 코틀린에서는 immutable
변수의 사용을 권장 한다.
var a: String = "initial" // 1
println(a)
val b: Int = 1 // 2
val c = 3 // 3
var
키워드를 이용해서String
타입의 이름이a
인 변수를 선언하고 값을initial
으로 초기화 했다. 이는mutable
변수로 값 변경이 가능하다.var
키워드가Javascript
의let
과 같은 역활 인듯 하다.- 표현방식은 키워드만 다를뿐,
Typescript
와 같은 것 같다.
val
키워드를 이용해서Int
타입의 이름이b
인 변수를 선언하고 값을1
로 초기화 했다. 이는immutable
변수로 값 변경이 불가능 하다.val
키워드가Javascript
의const
와 같은 역활 인듯 하다.val
로 선언된 변수는immutable
한 변수이기 때문에 새로운 값을 대입하지 못한다.
val
키워드를 이용해서 타입의 지정없이 이름이c
인 변수를 선언하고 값을3
으로 초기화 했다.Typescript
처럼 타입을 명시적으로 지정하지 않아도 초기화시 들어가는 데이터에 따라 컴파일시에 자동으로 타입을 지정 한다.
var e: Int // 1
println(e) // 2
var
키워드를 이용해서Int
타입의 이름이e
인 변수를 선언 하였다.변수
e
를 출력 한다.- 실행하면
Variable 'e' must be initialized
에러가 발생 한다. var
로 변수를 선언 할 때 변수를 초기화할 값을 지정하지 않으면 에러가 발생 한다.- 변수를 선언하고 초기화는 언제든 해도 상관 없지만, 사용하기전에는 초기화를 해야 한다.
- 실행하면
fun someCondition() = true
fun main() {
val d: Int // 1
if (someCondition()) {
d = 1 // 2
} else {
d = 2 // 2
}
println(d) // 3
}
val
키워드를 이용해서Int
타입의 이름이d
인 변수를 선언 하였다.someCondition()
의 결과에 따라d
변수의 값을1
또는2
로 지정 한다.val
의 경우Javascript
의const
같은 불변의 변수(immutable
)인데 바로 초기화 하지 않고 나중에 초기화를 하였다.- 실제
d
변수를 사용하기 이전에 선언한 변수의 값을 초기화하면 문제가 없는 것 같다.
- 변수
d
를 출력 한다.
Null Safety
NullPointerException
을 발생시키지 않기 위해서, 코틀린은 기본적으로 변수에 Null
을 할당을 허용하지 않는다. 하지만 Null
이 필요한 경우를 위해서 변수 선언시 타입뒤에 ?
를 붙여서 Null
을 허용(nullable) 할 수 있다.
var neverNull: String = "This can't be null" // 1
neverNull = null // 2
var nullable: String? = "You can keep a null here" // 3
nullable = null // 4
var inferredNonNull = "The compiler assumes non-null" // 5
inferredNonNull = null // 6
fun strLength(notNull: String): Int { // 7
return notNull.length
}
strLength(neverNull) // 8
strLength(nullable) // 9
non-nullable String
타입의neverNull
변수를 선언 하였다.var
키워드를 사용하여mutable
변수이기 때문에 값을 변경 할 수 있다.
1번에서 선언한
neverNull
변수에null
을 재 할당 한다.- 코틀린은 기본적으로
Null
을 허용하지 않기 때문에Null can not be a value of a non-null type String
에러가 발생 한다.
- 코틀린은 기본적으로
nullable String
타입의nullable
변수를 선언하였다.var
키워드를 사용하여mutable
변수이기 때문에 값을 변경 할 수 있다.
nullable
변수에null
을 재 할당 한다.- 타입 지정시
nullable
로 선언하였기 때문에 문제 없이null
을 할당 할 수 있다.
- 타입 지정시
타입을 지정하지 않고
inferredNonNull
변수를 선언 하였다.- 코틀린은 타입을 지정하지 않고 컴파일시 추론할 때
non-nullable
로 판단한다. - 만약
null
을 허용하는nullable
로 사용하려면 명시적으로nullable
타입으로 지정해야 한다.
- 코틀린은 타입을 지정하지 않고 컴파일시 추론할 때
5번에서 선언한
inferredNonNull
변수에null
을 재 할당 한다.null
을 할당 할 수 없는non-nullable
타입이기 때문에Null can not be a value of a non-null type String
에러가 발생 한다.
non-nullable String
을 파라미터로 받는strLength()
함수를 선언 한다.7번에서 선언한
strLength()
함수에non-nullable
로 선언한neverNull
변수를 인자로 넣어서 호출 한다.strLength()
함수 선언시 선언한 파라미터의 타입과 일치한 타입입의 인자를 입력하였기 때문에 문제 없이 정상적으로 함수가 호출 된다.
7번에서 선언한
strLength()
함수에nullable
로 선언한nullable
변수를 인자로 넣어서 호출 한다.strLength()
함수 선언시 선언한 파라미터의 타입과 일치하지 않는 타입의 인자를 입력하여Type mismatch: inferred type is Nothing? but String was expected
에러가 발생 한다.- 함수(function)사용시 파라미터의 지정된 타입도 중요하지만,
nullable
여부도 중요하게 판단해야 한다.
Working with Nulls
코틀린은 기본적으로 null
을 허용하지 않지만 외부의 자바코드와 상호작용하거나, 완전히 없는(선언되지 않은 것을 말 하는 것 같음)상태와 같이 null
을 이용해야 하는 경우 아래 코드와 같이 처리 하면 된다.
fun describeString(maybeString: String?): String { // 1
if (maybeString != null && maybeString.length > 0) { // 2
return "String of length ${maybeString.length}"
} else {
return "Empty or null string" // 3
}
}
nullable String
타입의 파라미터를 가지는describeString()
함수를 선언 하였다.describeString()
함수 호출시 입력한 인자maybeString
이null
이 아니고,maybeString
의 길이가 0보다 큰 경우 리턴되는 메시지.maybeString != null
조건에 대한 비교가 먼저 되기 때문에maybeString
이null
이 아닌 경우에만maybeString.length > 0
비교를 수행 한다.&&
는AND
연산자로 앞/뒤 조건이 모두 일치 할 경우만true
이다.
String
타입의 length를 출력 할 때 한글도 1글자로 인식한다. 유니코드를 사용해서 그런 것 같다. 함수 호출시String
문자열을 임의로 넣기 위해서describeString('abcd')
을 사용 하였는데,Too many characters in a character literal ''abcd''
,The character literal does not conform to the expected type String?
이런 에러메시지가 발생 함.'abcd'
=>"abcd"
로 변경하니 잘됨
차이는""
=>String
타입''
=>Char
타입으로 추론 함.
참고로, String(문자열)은"
로 감싸는 방식 말고"""
("
3개 사용)로 감싸는 방식도 존재
참고: Kotlin Reference Basic Type: String
참고: Kotlin Reference Basic Type: Char아래 코드는 String타입에서 값을 정의 할때 사용 가능한 표현에 대한 테스트(https://kotlinlang.org/docs/reference/basic-types.html#string-literals)
fun main() { val string1: String = "큰따음표만 사용할 경우\n\\n을 넣어서 한줄을 띄울 수 있고" val string2: String = """큰따음표 3개를 사용 했을 경우 이렇게 줄 변경해서 여러줄을 한번에 넣을 수 있음, 다만 \n와 같은 이스케이프 문자(?) 안먹힘 """ val string3: String = """큰따음표 3개의 경우 코드상의 줄마춤 대문에 의도치 않은 |들여쓰기가 되는데 이것을 제거하는 방법으로 |trimMargin()을 사용할 수 있음. |줄바뀜뒤 시작하는 문자의 제일앞에 prefix로 |를 기본 사용함 """.trimMargin() val string4: String = """preifx로 사용하는 문자도 변경 가능함 >trimMargin(">")의 인자로 원하는 문자를 입력하면됨 """.trimMargin(">") println(string1) println(string2) println(string3) println(string4) }
큰따음표만 사용할 경우 \n을 넣어서 한줄을 띄울 수 있고 큰따음표 3개를 사용 했을 경우 이렇게 줄 변경해서 여러줄을 한번에 넣을 수 있음, 다만 \n와 같은 이스케이프 문자(?) 안먹힘 큰따음표 3개의 경우 코드상의 줄마춤 대문에 의도치 않은 들여쓰기가 되는데 이것을 제거하는 방법으로 trimMargin()을 사용할 수 있음. 줄바뀜뒤 시작하는 문자의 제일앞에 prefix로 |를 기본 사용함 preifx로 사용하는 문자도 변경 가능함 trimMargin(">")의 인자로 원하는 문자를 입력하면됨
- 2번의 조건이
false
일 경우에 리턴 되는 메시지.
Classes
코틀린에서의 클래스 선언에 대한 간단한 예제를 통해 알아보는 것 같다. 클래스 부분은 예제의 내용보다 상당히 많은 내용이 있지만 이후 별도로 클래스만 다뤄서 다시 내용이 나오고, 여기서는 기초적인 선언하는 방법에 대해서만 알아보고자 한다.Class
는 이름, 헤더(클래스의 파라미터와 생성자(constructor
) 등), 중괄호({}
)로 싸여진 본문으로 구성되고, 헤더와, 본문의 내용이 없을 경우 중괄호({}
)는 생략이 가능 하다.
class Customer // 1
class Contact(val id: Int, var email: String) // 2
fun main() {
val customer = Customer() // 3
val contact = Contact(1, "mary@gmail.com") // 4
println(contact.id) // 5
contact.email = "jane@gmail.com" // 6
}
Customer
클래스를 선언하였다.- 헤더와 본문을 생략하고 이름만 선언 하였다.
Customer
클래스는 아무런 속성(properties
)를 가지고 있지 않고, 생성자(constructor
)의 경우 코틀린에서 기본 생성자로 자동 생성한다.
immutable Int
타입의ID
파라미터와mutable String
타입의email
파라미터를 가지는Contact
이름의 클래스를 선언 하였다.- 함수(function)를 선언하듯
ClassName(Parameter)
형식으로 선언하면 지정한Parameter
가 해당 클래스의 속성(property
)이 된다.
- 함수(function)를 선언하듯
customer
변수에Customer
클래스의 기본 생성자를 이용해서Customer Instance
를 만들어 할당 한다.- 코틀린에서는
new
키워드를 사용하지 않고 인스턴스(Instance
)를 생성 한다.
- 코틀린에서는
contact
변수에Contact
클래스의 2개의 인자를 넘겨Contact Instance
를 만들고 할당 한다.- 코틀린의 기본 생성자를 이용하여 2개의 인자를 각각의 속성(
property
)에 할당하여 인스턴스를 생성한다.
- 코틀린의 기본 생성자를 이용하여 2개의 인자를 각각의 속성(
contact
의id
속성(property
)의 내용을 출력 한다.contact
의email
속성(property
)의 내용을jane@gmail.com
로 변경 한다.
Class
에 대한 좀더 자세한 내용은 Kotlin Reference > Classes를 참고하자.
3일차 마무리 및 Next
3일차에는 코틀린의 변수와 클래스에 대해서 간단히 알아본것 같다.
변수(Variables
)의 특징으로 기본적으로 Null
을 허용하지 않고, Null
의 사용하기 위해서는 타입을 지정하고 명시적으로 nullable
로 선언해야 한다.
그리고 예제를 진행하면서 문자열을 사용하기 위한 String
타입와 문자를 지정한 Char
타입이 나뉘어져 있고, 타입을 지정하지 않을 경우 컴파일러가 타입 추론을 통해 타입을 유추하는데 이때 큰따음표("
)와 작은따음표('
)로 String
, Char
를 구분하기 때문에 Javascript
나 PHP
에서 처럼 섞어서 사용할 수 없다.
클래스(Classes
)의 경우는 매우 간단한하게 선언하고, 사용하는 방식에 대해서만 나왔고, 자세한 내용은 별도의 예제를 통해서 알려 줄것 같다.
다른 언어와 조금 다른점은 클래스를 사용할 때 new
키워드를 사용하지 않고, 그냥 함수를 호출하듯이 사용하면 된다는 것이다.
다음 시간에는 Generics
과 상속(Inheritance
)에 대해서 알아 보겠다.
- Kotlin 무작정 따라해보기 관련 Post
- 1일차 - Get Started
- 2일차 - Introduction > Hello World, Functions
- 3일차 - Introduction > Variables, Null Safety, Classes
- 4일차 - Introduction > Generics, Inheritance
- 5일차 - Control Flow