자바와 비교하면서 정리함.
코틀린은 함수형 프로그래밍을 표방하고 있다.
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)
val name:String? = null//값을 읽을 수만 있는 val
var address:String?= null//값을 읽고 쓰는 게 모두 가능한 var
lateinit var address2:String
//선언 시점에 값을 할당하지 않아도 에러 발생하지 않는다.
protected val b = 2
private val c = 3
internal val d = 4
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 fun onClick(v:view){}
자바에서는 final을 사용해 제한했다.
코틀린에서는 open 키워드를 사용해서 상속의 제한을 허용한다.
//클래스를 상속받을 수 있게 함.
open class OpenClass{
}
//프로퍼티 값을 상속한 클래스에서 재정의할 수 있게 함.
open val openProperty = 'park'
//open이 없다면 재정의 불가
단 하나의 인스턴스만 생성되도록 제약을 둔 디자인 패턴이다.
코틀린에서는 object 키워드 사용으로 가볍게 만든다.
object Seoul{
val hongdae = "hongdae"
fun go(){ }
}
//오브젝트 Seoul의 값 hongdae 참조
val seoulValue = Seoul.hongdae
//오브젝트 Seoul의 go()함수 호출
Seoul.go()
//기본 사용 방법
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
if(obj is Int){ //혹은 (obj !is Int)
....
}
자바의 switch문을 대체한다. 자바에서는 break를 사용하여 각 경우를 구분하지만, 코틀린은 중괄호를 사용해서 구분한다.
when(num){
0 -> Log.d(~~)
1,2 -> {
Log.i(~~)
}
//default 대신 else
else -> Log.e(~)
}
// 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)
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]}")
}
범위를 정의한다.
//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)
자바와 거의 동일하지만, 코틀린에서는 try-catch문은 값을 반환할 수 있다.
val nullableString : String? = null
// apple이 null 아닐 경우에는 apple을, null이라면 banana를 출력
apple ?: banana
// apple이 null 아닐 경우에는 해당 값을 대입, 그렇지 않은 경우 null을 에 대입
val fruit = apple?.aps
// apple이 null이 아닐 경우에만 run()을 호출
apple?.run()
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