코틀린(Kotlin) 기초


– 편안함을 추구하는 언어
– 간결함을 추구하는 언어
– 명령형 언어, 객체 지향 언어에서의 기능적 언어 개념


– 실용성
– 이미 검증되고 널리 알려진 언어 기능 채택

– 간결함
– 유형 추론(유형을 지정할 필요 없음), getter/setter

– 안정성(제로 보안)
– 상호 운용성(Java와 100% 호환성)

– 다양한 플랫폼 지원
– JVM 기반 서버, Android, Kotlin JavaScript, Kotlin 네이티브 IOS, MacOS, AndroidNDK, Windows, Linux

– 정적으로 입력된 언어
– 정적으로 입력된 lang. (자바, 코틀린)
– 동적으로 입력된 언어. (파이썬)

– 기능적 언어
– 오픈 소스(Kotlin의 새로운 기능을 만들 수 있음)


Java와 달리 Kotlin은 소스 파일의 위치 및 이름 지정에 대한 제한이 없습니다.
– 하나의 파일에 여러 클래스를 넣을 수 있습니다.
– 패키지 구조와 디렉토리 구조가 일치하지 않아도 됩니다.

패키지 com.example.mykotlin
/* 이 파일은 com/example/mykotlin/에 있을 필요가 없습니다.
이 파일의 이름은 원하는 대로 지정할 수 있습니다 */
재미있는 메인() {
println(“안녕, 코틀린”)
// Kotlin은 세미콜론이 필요하지 않습니다.
}
//Java와 달리 main() 함수는 독립적으로 존재합니다.


Kotlin에서 변수를 선언하는 키워드는 val과 var입니다.
– 변수 선언 키워드 뒤에 변수명, 콜론, 타입을 적는다.
-val
– val(?)로 선언된 변수는 허용되지 않음 -> 초기화 시 값 변경 불가
– 변수라고 부르지 말고 값이라고 부르세요.
– val 자체는 value의 줄임말입니다.

-var
var로 선언된 변수는 변경 가능
– 변수의 약자

값 a: Int = 10
변수 b: 정수 = 12
//a=11// 컴파일 오류
b = 13 // 확인

*발 a = 객체
개체의 멤버 변수 값을 변경할 수 있습니다.
그러나 a의 값을 변경하는 것은 불가능합니다.


– Kotlin 변수를 선언할 때 타입을 사용하지 않아도 컴파일러는 할당된 값을 기반으로 타입을 자동으로 결정합니다.


Java와 달리 Kotlin은 기본 유형과 래퍼 유형을 구분하지 않습니다.
– 바이트, Short, Int, Long, Float, Double, Char, Boolean
– UByte, UShort, UInt, ULong
Kotlin은 서로 다른 유형의 값을 자동으로 변환하지 않기 때문에 명시적으로 값을 변환해야 합니다.

값 i = 10
값 i2: UInt = 10U
//vale lov : Long = i// 컴파일 오류
val lov2 : Long = i.toLong() //명시적 값 캐스트(i.toLong()은 멤버 함수 메서드임)


– 구문은 Java와 유사하지만 Kotlin에서는 if를 명령문이 아닌 표현식으로 사용할 수 있습니다.
– 즉, if 문의 결과로 어떤 값이든 얻을 수 있습니다.
val x = if(a>10) “크다” 아니면 “작다”


– Kotlin에는 Java의 Object와 유사한 개념인 Any가 있습니다.
– Kotlin은 프리미티브 유형에 대해 Any를 지원합니다.
– 유형 테스트
– A는 유형입니다.

값 t : 모두 = 10
println((t는 int)) // 참


– A형을 B형으로 -> A형을 B형으로 변경(A와 B는 상호 상속)

재미있는 메인() {
재미있는 테스트(obj : Any){
if(obj는 Int입니다.) println(“obj는 Int입니다.”)
if(obj는 문자열입니다.) println(“obj는 문자열입니다.”)

println(“Obj를 문자열로 인쇄 > ${(Obj as? String ? : “”)}”})
}
시험(1)
// 객체는 int
// 객체를 문자열로 출력 > “”
테스트(“문자열”)
//obj는 문자열입니다.
//Obj를 문자열로 인쇄 > 문자열


– Java에서는 문자열 중간에 변수 값을 추가할 때 “+” 연산자를 사용했습니다.
Kotlin을 사용하면 변수(심지어 표현식)를 문자열에 넣을 수 있습니다.
– 삼중 따옴표가 있는 문자열 -> ‘ “”” ‘
– 모든 문자를 이스케이프 없이 작성할 수 있습니다.
– 여러 줄 문자열도 가능

var 버전=”1.3.50″
val javaStyle = “Hello, Kotlin” + 버전 + “!” -(하나)
val kotlinStyle = “안녕하세요, Kotlin ${version}!” -(2)
-> (1), (2)는 같다

값 번호 = 10
println(“val num은 10과 같습니다 : ${num==10}”)

println(“””\$”””) -> \$
println(“\$”) -> $


– Java와 달리 ‘==’ 연산자는 ‘객체 내용’을 비교하는 데 사용되며 ‘===’ 연산자는 ‘객체 참조’를 비교하는 데 사용됩니다.
Java에서 equals()는 객체 내용을 비교하는 데 사용됩니다.
== 연산자를 사용하여 문자열을 비교할 수도 있습니다.

데이터 클래스 MyClass(val a:Int, val b:String)
//데이터 클래스는 자동으로 equals/HashCode/toString/copy를 생성합니다.

재미있는 메인() {
val str1 = “안녕하세요, 코틀린”
var str2 = “안녕하세요, 코틀린”
값 Class1 = MyClass(10, “Class1”)
값 Class2 = MyClass(10, “Class1”)
값 Class3 = MyClass(20, “Class1”)
// 세 개체의 참조가 다릅니다.

println(str1==str2) //true(문자열 비교)
println(class1==class2) //true(문자열 비교)
println(class==class3) //false(문자열 비교)
println(class1===class2) //false(참조가 다르기 때문에)


– 배열은 arrayOf(), arrayOfNulls(), emptyArray()로 생성됩니다.

재미있는 메인() {
val intArrays = arrayOf(1,2,3,4,5) //유형 변환(int)이 필요하지 않음
val strArrays = arrayOfNulls(5) //5개 요소의 배열(유형 지정 – 문자열)
val dbArrays = 빈 배열() // 빈 배열의 유형 지정 – Double

println(intArrays(0)) // 배열 인덱스에 해당하는 값
intArrays(0) = 10 //val에 의해 정의된 배열이지만 배열의 값은 변경 가능
println(intArrays(0))

for(strArrays의){
인쇄(“$s, “)
}
프린트(“”)

println(dbArrays.size) // 배열의 크기
}


반복자와 함께 for 문을 사용하는 것이 편리합니다.
Range를 사용하여 특정 범위에 대한 반복자를 만들 수 있습니다.
– 범위는 첫 번째와 마지막 숫자(또는 문자)를 …로 연결합니다.
– 예) 1..10, ‘a’..’z’ (‘.’ – 2)

함수 메인(){
val array = arrayOf(“hello”, “that”, “is”, “Kotlin”)

for(a in array) //배열 인터레이터
인쇄(“$a”)
println(“”) //안녕하세요 코틀린입니다.

for((idx, a) in array.withIndex()) // 인덱스 포함
인쇄(“($idx, $a)”)
println(“”) //(0, 안녕하세요) (1, this) (2, is) (3, 코틀린)

for(i in 1..10) //범위 포함
인쇄(“$i”)
println(“”) //1 2 3 4 5 6 7 8 9 10

for(i in 1..10 step 2) // 범위 및 단계 포함
인쇄(“$i”)
println(“”) // 1 3 5 7 9 (2씩 점프)

(10 downTo 1).forEach{ //람다 포함(downTo 역방향)
print(“$it”) // 기본 인수입니다.
}
println(“”) //10 9 8 7 6 5 4 3 2 1

// ‘while’을 사용하는 경우
변수 나는 = 0
동안(i<10){
나++
인쇄(“$i”)
}
println(“”) //1 2 3 4 5 6 7 8 9 10
}


– 재미있는 함수 이름(매개변수 목록): 반환 유형 {함수 정의}
– fun function name (parameter list) = expression // 함수의 내용을 한 줄로 표현할 수 있다면
– 함수의 내용이 표현식인 경우 리턴 타입을 유추할 수 있으므로 생략한다.
– 기본 인수가 지원됨 – 인수가 제공되지 않은 경우 사용됨
– 명명된 인수 지원 – 인수 지정 시 매개변수 이름 및 값 지정에 사용

fun myFunc(arg1: Int, arg2: String = “default”, arg3: Int = 10)
{
println(“$인수1, $인수2, $인수3”)
}

재미있는 sumFunc(a: Int, b: Int) = a+b

재미있는 메인() {
myFun(1, “안녕하세요”, 5) //1, 안녕하세요, 5
myFun(arg1=2) //2, 기본값, 10
myFunc(2, arg3=5) //2, 기본값, 5

//로컬 함수
재미있는 localFunc(a: Int) : Int{
+ 10 반환
}
println(sumFunc(1,2)) //3
println(localFunc(10) //20
}

– Lambda 함수는 익명 함수입니다.
– Lambda 함수는 {argument list -> function content} 형식으로 작성
– 인자가 1개이고 타입 생략이 가능한 경우 기본 인자를 이용하여 인자 목록 부분 생략 가능
– 람다함수는 별도의 리턴을 사용하지 않으므로 (x+y)식으로 표현한다.

val sum = {x: Int, y: Int -> x+y} // 람다 함수 정의
println(합계(10, 20))

fun lambdaTest(a: (Int) -> Int) : Int{ //(int) 인자를 받아 int를 반환하는 타입
a(10)를 반환합니다.
}

lambdaTest({x -> x+10}) //ie {x: Int -> x+10}
lambdaTest({it + 10}) //인수 타입은 생략 가능, 인수는 1개이므로 인수 목록 생략
lambdaTest{it + 10} //lambda가 함수의 유일한 인수인 경우 함수 괄호를 생략할 수 있습니다(lambdaTest 함수의 인수 {it+10}로 지정됨).

데이터 클래스 MyClass(val a: Int, val b: String)

재미있는 LambdaTest (a: (int) -> int): int {
}

재미있는 메인() {
합계 = {x: 정수, y: 정수 -> x+y}
println(합계(10, 20))

배열 배열 = arrayOf(MyClass(10, “class1”), MyClass(20, “class2”), MyClass(30, “class3”))
println(array.filter({c: MyClass -> ca < 15})) //(MyClass(a=10, b=class2))
//Filter는 함수를 매개변수로 받아 각 요소에 대한 함수의 조건에 따라 실행하고 참 값만 씁니다.
//c는 MyClass를 수신하고 MyClass의 속성 a의 조건은 15 미만입니다.
//함수의 마지막 인자로 람다를 사용하면 함수의 괄호에서 빼낼 수 있다.

array.filter() {c:MyClass -> ca < 15}
// 람다가 함수의 유일한 인수인 경우 함수 대괄호를 생략할 수 있습니다.

array.filter{c: MyClass -> ca <15}
//인수 타입을 생략할 수 있는 경우

배열.필터 {it.a < 15}
//표준 매개변수 이름으로 사용할 수 있으며 일반적으로 사용되는 형식입니다.

인쇄(lambdaTest{it + 10})

val title=”숫자:”
값 목록 = ListOf(1,2,3,4)
list.forEach{println(“$title $it)} //람다 외부의 제목에 액세스
}


– Android 프로그래밍에서 자주 사용되는 예제

1- 값 btn = findViewById