일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 파이썬강좌
- 딥러닝공부
- 머신러닝 강의
- 파이썬강의
- 머신러닝 강좌
- 머신러닝
- python강좌
- acmicpc.net
- 비용함수
- 인공지능
- supervised learning
- 자바시작하기
- Python강의
- 자바
- C언어
- 백준 알고리즘
- 머신러닝공부
- 경사하강법
- feature scaling
- 딥러닝
- 비지도학습
- JAVA강좌
- 자바강좌
- 선형회귀
- Gradient Descent
- c언어 오목
- 지도학습
- 효묘블로그
- java
- unsupervised learning
- Today
- Total
컴공과컴맹효묘의블로그
Kotlin 본문
[코틀린]
Kotlin은 JetBrains에서 개발한 프로그래밍 언어. 2011에 처음 공개됨. 2017년 구글에서 안드로이드 공식 언어로 지정.
코틀린의 특징
- 표현력과 간결함.
- 안전한 코드. Null safety를 지원한다. 변수를 nullable과 not null로 구분해서 선언한다.
- 상호 운용성. Kotlin은 Java와 100% 호환.
- 구조화 동시성. Coroutines라는 기법으로 비동기 프로그래밍을 간소화 할 수 있다.
코틀린 파일 구성
패키지 경로가 다르다면 import문으로 불러와야하지만, 같다면 그럴 필요가 없다.
자바와는 다르게 파일명과 클래스명을 다르게 선언해도 된다.
예를 들어 Test.kt
라는 코틀린 파일에 다음과 같은 내용이 작성되어있다면, Test
클래스인 Test.class
와 Test.kt
의 최상위에 선언되어있는 변수 num
과 함수 sum
은 TestKt.class
라는 파일에 자동적으로 포함된다.
// Test.kt
// 패키지문, 임포트문 생략
var num = 10
fun sum(x: Int, y: Iny): Int {
return x + y
}
class Test {
var name = "Alex"
fun printName() {
println("$name")
}
}
[변수 선언]
코틀린은 val
과 var
키워드로 선언한다.
val
은 value의 줄임말로 초기 할당 후 바꿀 수 없는 변수다.
var
은 variable의 줄임말로 언제든지 값을 바꿀 수 있다.
val name: String = "Hyomyo"
var num: Int = 10
코틀린의 타입 명시는 타입이 추론 가능할 때 생략 가능하다.
초깃값, 초깃값 미루기- lateinit, lazy
최상위에 선언된 변수 혹은, 클래스의 멤버 변수는 선언과 동시에 초깃값을 할당해야 한다.
lateinit
lateinit
으로 초깃값 선언을 미룰 수 있다. 단, var
키워드로 선언한 변수에서만 가능하다.
그리고, Int
, Long
, Short
, Double
, Float
, Boolean
, Byte
타입은 lateinit
이 불가능하다.
lazy
변수 선언문 뒤에 by lazy {..}
로 선언한다. lazy
를 적용한 변수를 처음 사용할 때 brace안의 구문이 실행되며, brace 마지막 줄이 변수 초깃값으로 할당된다.
데이터 타입
코틀린의 모든 변수는 객체다. 흔이 쓰는 정수 Int
타입도 primitive type이 아니라 객체이다. 따라서 Int
에도 null이 대입 될 수 있다.
fun function() {
var num1: Int = 10
var num2: Int? = null
println(num1.toString())
}
효율성에 의문이 들 수 있지만 코틀린은 컴파일 할 때 Collection이나 Generic을 사용하는 경우 이외에는 Java의 int
로 변환된다.
형 변환
자바와 다르게 기초 타입 객체끼리의 자동 형 변환이 없다. 변수에 .toLong()
과 같이 표현해서 사용해야한다.
Int, Short, Long, Double, Float, Boolea, Byte- 기초 타입 객체
val num1: Int = 10
val num2: Short = 20
val num3: Long = 123456L
val num4: Double = 10.0
val num5: Float = 10.0f
val num6: 0b00101001
val num7: Boolean = true
val num8: Int = 0x0F // 16진수 리터럴 상수
Char, String- 문자와 문자열
Char
는 문자 표현 타입이다. 문자를 작은 따옴표 '
로 감싸서 표현. Number타입으로는 표현할 수 없다.
String
은 문자열 표현 타입이다. 큰 따옴표"
나 삼중 따옴표"""
로 감싸서 사용된다.
문자열 템플릿 $
문자열 템플릿이 가능하다.
println("name: ${user.name} date: $date")
[Any- 모든 타입]
Any
는 코틀린에서 최상위 클래스이다. Any
타입으로 선언한 변수는 모든 타입의 데이터를 할당할 수 있다.
Unit- 반환문이 없는 함수
Unit
은 변수 선언 타입이 아닌 함수 반환문이 없음을 명시적으로 표현할 때 사용한다.
fun printQueue(): Unit {
// ...
}
Nothing- null이나 예외를 반환하는 함수
Nothing
도 Unit
과 마찬가지로 함수에 반환 타입에 사용된다.
fun function1(): Nothing? {
return null
}
fun function2(): Nothing {
return Exception()
}
Nullable과 Not null
코틀린은 변수를 선언할 때 null을 대입할 수 있는지, null이 아닌지 명시를 해야한다.
var data1: Int = 10 // Not null. null을 대입할 수 없음
data1 = null // 에러
var data2: Int? = 10 // Nullable.
data2 = null
함수 선언
fun 함수명(매개변수명: 타입): 반환타입 {
// ...
}
반환 타입을 생략하면 Unit
타입이 자동으로 적용된다.
함수 매개변수에 var
이나 val
키워드를 작성할 수 없으며 자동으로 val
타입이 적용된다.
기본값 default value를 설정할 수 있다.
fun sum(a: Int, b: Int = 10): Int {
return a + b
}
매개변수를 지정해서 호출named parameter할 수 있다.
sum(b = 20, a = 12)
[컬렉션 타입 Colleciton type]
Collection type은 여러 개의 데이터를 표현하는 방법.Array
, List
, Set
, Map
이 있다.
Array- 배열
코틀린의 배열은 Array
클래스로 표현한다.
Array의 첫 번째 매개변수는 크기size를 지정하며 두 번째 매개변수는 초깃값init을 지정한다.
<init>(size: Int, init: (Int) -> T)
배열의 타입은 제너릭generic으로 표현한다.
val arr: Array<Int> = Array(3, { 0 })
두 번째 매개변수는 0을 반환하는 람다 함수이다.
배열의 제너릭이 기초 객체 타입이라면 IntArray
, LongArray
, ShortArray
, DoubleArray
, FloatArray
, BooleanArray
, ByteArray
, CharArray
를 이용할 수도 있다.
arrayOf()
라는 함수를 사용해서 배열을 선언할 때 값을 할당할 수도 있다.
val arr = arrayOf<Int>(10, 20, 30) // 배열에 10, 20, 30 대입
println("size: ${arr.size}") // 3
arrayOf()
함수도 기초 객체 타입을 대상으로 하는 intArrayOf()
, BooleanArrayOf()
... (생략)... 함수를 제공한다.
List, Set, Map
- List: 데이터의 순서가 있고 값 중복 허용.
- Set: 데이터의 순서가 없고 값 중복 불허. 수학의 집합과 같음.
- Map: key와 value라는 데이터 순서쌍으로 이루어진 데이터 집합. 순서가 없고, key의 중복 불허.
Collection type의 mutable과 immutable
Collection 타입 클래스는 가변mutable과 불변immutable로 나뉜다.
immutable 클래스는 초기에 값을 할당하면 변경할 수 없다.
var list = listOf<Int>(10, 20, 30) // 불변immutable이다.
var mutableList = mutableListOf<Int>(10, 20, 30) // 가변mutable이다.
immutable 클래스 타입은 List
, Set
, Map
immutable 클래스 함수는 listOf()
, setOf()
, mapOf()
mutable 클래스 타입은 MutableList
, MutableSet
, MutableMap
mutable 클래스 함수는 mutableListOf()
, mutableSetOf()
, mutableMapOf()
Array
클래스는 항상 mutable이다. 참고
Map
객체는 Pair
객체를 이용하거나 key to value
로 이용할 수 있다.
fun main() {
var map = mapOf<String, String>(Pair("Pale", "Beer"), "Whisky" to "Spirits")
}
[조건문 if~else 와 when 그리고 표현식]
Kotlin의 if~else
문은 표현식으로도 사용할 수 있다. 단, 표현식으로 사용하려면 else
를 생략할 수 없다.
표현식의 반환값은 brace안의 각 마지막 문장이다.
fun main() {
var num = 3
var isPositive = if (var >= 0) {
println("Positive")
true
} else {
println("Negative")
false
}
}
when
은 switch ~ case
문 같은 역할을 한다.
fun main() {
var data = 3
when (data) {
is String -> println("data is String type")
0 -> println("data is 0")
in 1..10 -> println("data is in 1..10") // 1이상 10이하
else -> println("data is invalid")
}
}
when(data)
의 소괄호()
를 생략해도 된다.
fun main() {
var data = 3
when {
data < 0 -> println("data is negative")
data >= 0 -> println("data is positive")
else -> println("data is invalid")
}
}
when
문 또한 표현식으로도 사용 가능하다. 마찬가지로 else
를 생략할 수 없다.
fun main() {
var data = 3
val result = when {
data > 0 -> "data is positive"
data < 0 -> "data is negative"
data == 0 -> "data is 0"
else -> "data is not a number"
}
}
[반복문 for, while]
for (i in 1..10) { ... } // 1부터 10까지 1씩 증가
for (i in 1 until 10) { ... } // 1부터 9까지 1씩 증가
for (i in 2..10 step 2) { ... } // 2부터 10까지 2씩 증가
for (i in 10 downTo 1) { ... } // 10 부터 1까지 1씩 감소
collection.indices
를 사용해서 컬렉션 타입의 데이터 개수만큼 반복할 수 있다.
collection.withIndex()
함수를 사용하면 인덱스와 값을 동시에 가져올 수 있다.
fun main() {
var data1 = arrayOf<Int> (1, 2, 3)
var data2 = arrayOf<Int> (10, 20, 30)
for (i in data1.indices) {
print("$data[i] ")
}
println("")
for ((index, value) in data2.withIndex()) {
print("$index: $value")
}
}
while
은 조건이 참일때 {}
영역을 반복 실행한다.
[객체지향 코틀린]
class
키워드로 클래스를 선언한다.
class Test { }
객체 생성은 다음과 같이 한다. new
키워드를 사용하지 않는다.
val user = User("myName", 82)
클래스의 멤버는 생성자, 변수, 함수, 클래스로 구성된다.
생성자의 키워드는 constructor
이다.
주 생성자
생성자는 주 생성자와 보조 생성자로 나뉜다. 각각 따로 사용해도 되고 둘 다 동시에 사용해도 된다.
- 주 생성자
class User consturctor() { }
- 주 생성자 키워드 생략
class User() { }
- 매개변수가 없을 때 생략
class User { }
주 생성자는 init
영역에서 초기화를 한다. 단, 주 생성자의 매개변수는 지역변수이므로 클래스 내 다른 곳에서는 사용할 수 없다.
class User(name: String, userId: Int) {
init {
println("name: $name user_id: $userId")
}
fun function() {
// name, userId 사용 불가
}
}
클래스 멤버변수에 저장해서 사용 가능하다.
class User(name: String, countryNumber: Int) {
var name: String
var countryNumber: Int
init {
this.name = name
this.countryNumber = Int
}
}
val
혹은 var
키워드를 이용해서 매개변수를 받는 동시에 멤버변수로 만들 수 있다.
class User(val name: String, val height: Double) { }
보조 생성자
counstuctor
키워드로 생성하며 한 클래스에 여러 보조 생성자를 생성할 수 있다.
class User {
consturctor(name: String) {
}
consturctor(name: String, num: Int) {
}
}
주 생성자와 보조 생성자를 같이 선언하는 경우 보조 생성자에서 주 생성자를 어떤 식이로든 꼭 호출해야 한다.
호출하는 방법은 this
키워드를 이용한다.
class User(name: String) {
consturctor(name: String, num: Int): this(name) {
}
consturctor(name: String, num: Int, sex: String): this(name, num) {
}
}
fun main() {
val user = User("myName", 82, "male")
}
상속과 생성자
클래스를 선언할 때 다른 클래스를 참조해서 선언하는 것을 상속inheritance라고 한다.
다음은 Dog
클래스가 Animal
클래스를 상속하는 코드이다.
open
키워드를 사용해 상속이 가능한지 결정한다.
open class Animal { // 상위 클래스 Animal
}
class Dog: Animal() { // 하위 클래스 Dog
}
하위 클래스에 보조 생성자만 있는 경우 다음과 같이 가능하다.
open class Animal(name: String) { // 상위 클래스 Animal
}
class Dog: Animal { // 하위 클래스 Dog
constructor(name: String): super(name)
}
오버라이딩 Overriding
오버라이딩은 상위 클래스의 멤버 변수나 함수를 같은 이름으로 재정의 하는 것을 말한다.
자바는 @Override
라는 annotaion 을 명시해서 사용하지만, 굳이 명시하지 않아도 overriding이 가능했다.
코틀린은 이러한 모호성을 없애기 위해 override
라는 키워드를 이용해야만 overriding이 가능하다.
또한 상위 클래스의 멤버 변수나 함수가 open
키워드로 작성되어야 한다.
open class Parents {
open var num = 10
open fun function() {
println("Parents")
}
}
class Child: Parents {
override var num = 10
override fun function() {
println("Child")
}
}
접근 제한자 visibility modifier
코틀린의 접근 제한자는 public
, internal
, protected
, private
가 있다.
접근 제한자 | 최상위 선언 | 클래스 멤버로 선언 |
---|---|---|
public |
모든 파일 가능 | 모든 클래스 가능 |
internal |
같은 모듈 내에서 가능 | 같은 모듈 내에서 가능 |
protected |
사용 불가 | 상속 관계의 하위 클래스에서 가능 |
private |
파일 내부에서만 가능 | 클래스 내부에서만 가능 |
[클래스 종류]
data class
data
키워드로 선언. VO(value-object) 를 편리하게 이용하도록 해줌.
data class DataClass( ... )
데이터 클래스는 객체의 equals()
함수로 멤버 변수의 값을 비교해줌. 일반 클래스는 객체 자체를 비교함.
데이터 클래스는 toString()
함수를 사용하면 객체의 데이터 정보들을 반환해줌.
object class
오브젝트 클래스는 익명 클래스 anonymous class를 사용할 목적으로 만들어졌다.
object
키워드로 생성한다.
val obj = object {
var name = "Hello"
fun printName() {
println("name: $name")
}
}
fun main() {
obj.name = "world" // 에러
obj.printName() // 에러
}
오브젝트 클래스는 타입을 명시하지 않으면 최상위 클래스인 Any
타입으로 취급한다. 따라서 name
같은 멤버 변수에는 접근할 수 없다.
object: A { }
처럼 선언하면 A
라는 클래스를 상속, 혹은 A
라는 인터페이스를 구현한 익명 클래스가 생성된다.
따라서 A
객체의 멤버 변수나 메소드를 overriding할 수 있고 사용할 수도 있다.
companion class
컴패니언 클래스는 객체를 생성하지 않고 클래스에 접근할 때 사용한다. 자바의 static
과 유사하지만 코틀린에서는 최상위에 변수나 함수를 선언할 수 있으므로 static
이 필요하지 않다.
클래스 내부에 companion object { }
로 선언한다.
class Test {
companion object {
var data = 1
fun func() {
println(data)
}
}
}
fun main() {
Test.data = 10
Test.func()
}
[람다 함수]
람다함수 혹은 람다식은 함수를 간단하게 정의할 때 사용되는 익명함수 anonymous function 정의 기법이다.
람다 함수는 다음과 같이 정의된다.
{ 매개변수 -> 함수 본문 }
val sum = {a: Int, b: Int -> a + b }
sum(a, b)
선언과 동시에 호출하는 방법이다.
{a: Int, b: Int -> a + b}(10, 20)
매개변수가 없으면 화살표를 생략해도 된다.
{-> println("Hello world!")}
{println("Hello world!")}
매개변수가 1개라면 다음과 같이 작성할 수 있다. 단, 타입 식별이 가능해야한다.
val some = {num: Int -> println(num)}
some(10)
// --- --- --- ---
val some: (Int) -> Unit = {println(it)}
some(10)
(Int)->Unit
을 함수 타입이라고 한다. 이 때 it
키워드를 사용하면 생략된 매개변수를 이용할 수 있다.
람다 함수 반환
람다함수는 마지막 문장을 반환한다. return
키워드를 사용할 수 없다.
val func = {a: Int, b: Int ->
println("adding...")
a + b
}
함수 타입 선언- typealias
매개변수와 반환타입을 표현할 수 있다. 예를 들어, Int
타입 매개변수 두 개와 Int
타입을 반환하는 함수는 (Int, Int)->Int
으로 표현할 수 있다.
val func: (Int, Int) -> Int = {a: Int, b:Int -> a + b}
typealias
를 이용해 함수 타입이나 데이터 타입을 선언할 수 있다.
typealias CustomInt = Int
typealias CustomFunc = (Int, Int) -> Boolean
fun main() {
val data: CustomInt = 10
val func: CustomFunc = {a: Int, b: Int -> a > b}
}
매개변수 타입을 유추할 수 있다면 생략 가능하다.
typealias CustomFunc = (Int, Int) -> Boolean
fun main() {
val func: CustomFunc = {a, b -> a > b}
}
고차 함수 high order function
고차 함수란, 매개변수로 함수를 전달받거나, 반환값이 함수인 함수를 말한다.
fun function(arg: (Int) -> Boolean): () -> String {
val result = if(arg(10)) {
"valid"
else {
"invalid"
}
return {"result: $result"}
}
fun main() {
val result = function({no -> no > 0})
println(result())
}
[널null 안정성]
널 안정성이란 NullPointException이 발생하지 않도록 코드를 작성하는 것이다.
자바에서는 null 안정성을 고려해서 많은 코드를 짜야했지만 코틀린에서는 간단하게 null 안정성을 처리할 수 있다.
널 허용- ? 연산자
변수 타입 뒤에 ?
를 붙이면 nullable이고 붙지 않으면 not null이다.
var name: String? = null
var hello: String = "Hello"
널 안정성 호출- ?. 연산자
?.
연산자는 변수가 null이 아니면 멤버에 접근을 할 수 있고, null이면 null
을 반환한다.
name?.length
엘비스- ?: 연산자
엘비스 연산자는 변수가 null
이면 ?:
뒤에 있는 값을, null
이 아니면 변수를 반환한다.
var data: String? = "my name"
println("data: $data: ${data?.length ?: -1}") // data = my name: 7
data = null
println("data: $data: ${data?.length ?: -1}") // data = null: -1
예외 발생- !!연산자
!!
는 객체가 널일 때 예외exception을 일으키는 연산자다.
data!!.length
'컴퓨터 > Android Studio' 카테고리의 다른 글
Android- 액션바ActionBar와 툴바Toobar (0) | 2022.03.03 |
---|---|
Android- 플랫폼API, 제트팩 라이브러리 (0) | 2022.03.03 |
Android- platfrom architecture (0) | 2022.03.03 |
Android- viewBinding (0) | 2022.03.02 |
Android- Permisson (0) | 2022.03.02 |