kotlin 문법

park paul·2021년 11월 18일
0

코틀린 문법 정리

자바와 비교하면서 정리함.
코틀린은 함수형 프로그래밍을 표방하고 있다.

변수 할당

var c :Char ='A'
val text:String ="dfdf"
val length : Int=3000
val lengthText: String = "TextLength: ${text.length}"

배열

val words:Array<String> = arrayOf("fad","dgd","gdgd")
            }
val intArr: IntArray = intArrayOf(1,2,3,4,5)

Mutable, Immutable

val name:String? = null//값을 읽을 수만 있는 val
var address:String?= null//값을 읽고 쓰는 게 모두 가능한 var

lateinit

lateinit var address2:String
  //선언 시점에 값을 할당하지 않아도 에러 발생하지 않는다.

접근 제한자

  • 자바와 비슷하지만 public을 쓰지 않아도 아무것도 쓰지 않으면 public으로 간주한다.
protected val b = 2
private val c = 3
internal val d = 4

생성자

  • init블록을 사용한다.
class Kal{
    	init{
        	//생성자에서 수행할 작업들
        }
   }
  • 간결하게 이렇게도 가능하다.
class Jet(val a: Int, val b: Char)

but 코틀린에서는 추가 생성자를 정의할 때는 주 생성자를 반드시 호출해야 한다.

함수

자바에서는 아무 값도 반환하지 않는 함수는 void를 썼는데, 코틀린에서는 이렇다.

class Aiffel{
	//아무 값도 반환하지 않는 함수
    fun deep(): Unit{
    
    }
    
    //정수 값을 반환하는 함수
    private fun machine():Int{
    	return 0
    }
}

상속 및 인터페이스 구현

자바에서는 extends와 implements로 구분했다.
코틀린에서는 이 구분없이 :으로 처리한다.

class MainActivity:
	AppCompatActivity(),
    	View.OnClickListener{
	 ...
}

override

자바에서는 @override 애노테이션으로 명시했다.
코틀린에서는 상속받거나 구현한 함수 앞에 override 키워드를 붙인다.

override fun onClick(v:view){}

open 키워드

자바에서는 final을 사용해 제한했다.
코틀린에서는 open 키워드를 사용해서 상속의 제한을 허용한다.

//클래스를 상속받을 수 있게 함.
open class OpenClass{
}

//프로퍼티 값을 상속한 클래스에서 재정의할 수 있게 함.
open val openProperty = 'park'

//open이 없다면 재정의 불가

Singleton

단 하나의 인스턴스만 생성되도록 제약을 둔 디자인 패턴이다.
코틀린에서는 object 키워드 사용으로 가볍게 만든다.

object Seoul{
	val hongdae = "hongdae"
    fun go(){ }
 }
  • 사용은
//오브젝트 Seoul의 값 hongdae 참조
val seoulValue = Seoul.hongdae

//오브젝트 Seoul의 go()함수 호출
Seoul.go()

enum 클래스

//기본 사용 방법
enum class Direction{
	NORTH, SOUTH, WEST, EAST
}

//필드와 프로퍼티를 추가하는 방법
enum class Direction(val label:String){
	NORTH("N"), SOUTH("S"), WEST("W"), EAST("E")
}

자료/자료형의 확인 및 변환

  • 자료의 동일성 확인: ==, === 연산자
val equals : Boolean = foo == bar
  • 자료형 확인: is 연산자
if(obj is Int){ //혹은 (obj !is Int)
  ....
}

when문

자바의 switch문을 대체한다. 자바에서는 break를 사용하여 각 경우를 구분하지만, 코틀린은 중괄호를 사용해서 구분한다.

when(num){
	0 -> Log.d(~~)
    
    	1,2 -> {
        Log.i(~~) 
        }
        
        //default 대신 else
        else -> Log.e(~)
}

while문

// while문
var a:Int = 0
var b:Int = 10

while(a<b) {
	Log.d("Number", "a=$a b=$b")
   a+=2
   b++
}

//do while문

var a: Int = 0
var b: Int = 10

do{
	Log.d("Number", "a=$a b=$b")
   a+=2
   b++
}while(a>b)

for문

val names: List<String> = ...// 이름 목록

for (name in names) {
	Log.d("Name","name="+ name)
}

//for문에서 인덱스 접근하기
Collection.indicies프로퍼티를 사용하면 컬렉션의 인덱스를 순환하며 인덱스 인자로 배열 내 항목에 접근할 수 있다.

val names: List<String> = ...//이름 목록

for (i in names.indicise) {
	//인덱스 인자로 배열 내 항목 접근
    Log.e("Name", "name=${names[i]}")
}

range

범위를 정의한다.

//0~10을 정의할 때
val myRange : IntRange = 0..10

//이를 가지고 for문을 돌리면
for (i in myRange){ // (0~10까지)
	//처리할 코드
}

// 또는 바로 range를 적용 시킬 수 있다.
for (i in 0..10) {
	//처리할 코드
}

// until을 사용하면 마지막 값은 포함하지 않는다.
val myRange2 : IntRange = 0 until 4 //(0~3까지)

// 범위에 따른 boolean값 반환
val myRange2 : Boolean = 2 in myRange2 // true

// downTo()를 사용하여 reversed order
for (i in 5 downTo 1) {
	System.out.print(i)
 } //5부터 1씩 감소한다. 기본적으로 downTo는 1씩 감소 (in in 10 downTo 1 step2)// 2씩 감소

제네릭

제네릭은 인자로 사용하는 타입에 따라 구체화되는 클래스나 인터페이스이다.

val names: List<String>
val entries: Map<String, String>

//예
class Car {
  ...
}
// 항목을 담거나 뺄 수 있는
// 제네릭 인터페이스 Container 정의
interface Container<T> {
	fun put(item: T)
    	fun take(): T
}

// 자동차(Car)를 담거나 뺄 수 있는 클래스 Garage 정의
class Garage: Container<Car> {
	
    override fun put(item:Car) {
    	...
    }
    
    override fun take(): Car {
        ...
    }
}

//제네릭 클래스나 인터페이스가 인자로 받을 수 있는 타입을 한정하는 방법
interface Container<T: Car> {
	fun put(item: T)
    	fun take(): T
}

//타입이 정의되어 있는 제네릭을 인자로 받는 예
fun processItems(
	items: List<String>) {
    ...
}

//호출 시점에 타입이 정해지는 제네릭을 인자로 받는 예
fun <T> processItems(Items: List<T>) {
	...
}

사용 예)

open class Car {...}

class Sedan: Car() {...}

class Truck: Car() {...}

fun <T> append(dest: MutableList<in T>,
	src: List<out T>) {
    	dest.addAll(src)
}

// 일반 승용차 리스트 생성
val sedans: List<Sedan> = ...

// 트럭 리스트 생성
val trucks: List<Truck> = ...

// 자동차를 담을 수 있는 리스트 생성
val cars: MutableList<Car> = ...
// 자동차를 담는 리스트에 일반 승용차 리스트 추가
append(cars, sedans)
// 자동차를 담는 리스트에 트럭 리스트 추가
append(cars, trucks)

Exception

자바와 거의 동일하지만, 코틀린에서는 try-catch문은 값을 반환할 수 있다.

Nullable

  • null 표기
    코틀린에서는 별도의 표기가 없을 경우 널 값을 허용하지 않는다.
    널 값을 가질 수 있도록 하려면 명시적으로 타입 뒤에 ?를 붙여준다.
val nullableString : String? = null
  • null 대신 엘비스 연산자 (?:)
// apple이 null 아닐 경우에는 apple을, null이라면 banana를 출력
apple ?: banana
  • null 확인과 처리를 한번에 할 수 있는 (?.) 연산자
    자바에서는 널 값 여부를 주로 if문으로 처리해서 사용했다.
    복잡한 경우일수록 효율을 크게 떨어진다.
// apple이 null 아닐 경우에는 해당 값을 대입, 그렇지 않은 경우 null을 에 대입
val fruit = apple?.aps

// apple이 null이 아닐 경우에만 run()을 호출
apple?.run()

lateinit

lateinit 키워드를 사용하면 초기화 없이 변수만 선언할 수 있다.

class MyActivity: Activity(){

	// 나중에 초기화를 수행할 객체로 표시하였으므로 바로 초기화를 하지 않아도 된다.
     	lateinit var api: Api
        ...
  }

데이터 클래스

data class Person(val name: String, val address: String)

함수의 단일 표현식 표기

Unit타입을 제외한 타입을 반환하는 함수라면 단일 표현식 표기가 가능하다.

fun everyting(): Int {
	return 21*2
  }
 //이것을 단일 표현식으로 바꾸면
 fun everything(): Int = 21*2
 //반환 타입도 생략이 가능해진다.
 fun everything(): 21*2
profile
Innovation is mine

0개의 댓글