코틀린 (Kotlin) by 키워드 정리

코틀린 by 키워드 개발하다 보면 하위 클래스가 상위 클래스를 상속해서 상위 클래스 메소드를 오버라이드를 하는 경우가 많습니다. 이러한 상황에서 유지보수를 하다보면 상위 클래스가 변경이되는 경우 하위 클래스가 상위 클래스에 의존하고 있던 상황이 변경되면서 예기치 않은 오류가 발생합니다. 그래서 코틀린에서는 기본적으로 클래스는 final 입니다. 상속가능한 클래스는 open 을 해서 상속이 가능하다는 것을 알려줍니다. 상위 클래스 변경 시 하위 클래스에 영향을 줄 수 있다는 것을 인지시켜 줄수 있습니다. by - 위임 상속을 허용하지 않는 클래스에 새로운 기능을 추가 할때는 위임을 사용할 수 있습니다. 위임을 사용하면 상속하지 않고 기존 기능을 그대로 사용하면서 새로운 기능을 추가 할 수 있습니다. 코틀린에서는 by 키워드 를 사용하여 위임 기능을 사용할 수 있습니다. //상속하지않고 새로운 함수 추가하기 class CountingSet<T> (     val innerSet : MutableCollection <T> = HashSet () ) : MutableCollection <T> by innerSet { //MutableCollection 구현을 innerSet 에 위임      var objectsAdded = 0 //카운트     //override 함수는 HashSet() 대신 구현한 것을 사용      override fun add(element: T): Boolean {           objectsAdded ++    //add할때마다 카운트 증가           return innerSet.add(element)     }...

코틀린 (Kotlin) 데이터 클래스 정리

데이터 클래스 data class 는 toString , equals , hashcode 함수를 자동 생성 해 줍니다. 그래서 자바와 다르게 코틀린에서 == 은 equals 를 호출합니다. 자바처럼 참조를 호출하려면 === 을 사용합니다. data class Client( val name : String, val code : String) 데이터 클래스 - copy() 함수 제공 데이터 클래스는 copy() 함수를 제공합니다. 코틀린에서 프로퍼티는 val 또는 var 도 가능합니다. 그러나 데이터 클래스의 모든 프로퍼티를 읽기 전용(val)으로 만들어 불변 클래스로 만들기를 권장합니다. 다중 스레드일때 값이 변경되어 동기화할 필요가 줄어들도록 하기 위해서입니다. 객체를 메모리에서 값을 변경하는 것보다 복사본을 만드는 것이 더 좋습니다. public final class Client {     public final Client copy (@NotNull String name, @NotNull String code) {         return new Client(name, code)  //새로운 객체를 생성해서 복사     } } //사용 val client = Client( "zerog" , "1111" ) val clientCopy = client. copy ( "zerog2" , "2222" ) //복사 *개인적으로 코틀린을 공부하면서 정리한 자료입니다. 수정 사항 및 이슈가 있는 경우 메일 부탁드립니다.

코틀린 (Kotlin) 생성자 정리

주 생성자와 초기화 블록 코틀린의 주 생성자는 클래스 이름 뒤에 괄호로 둘러쌓여 있습니다. open class User constructor (_nicname:String) { // 주생성자     val nickname: String     init {         //주생성자와 함께 초기화 블럭         //init 초기화 블록은 여러개 가능         nickname = _nicname     } } constructor 는 주 생성자 나 부 생성자 를 정의합니다. init 은 초기화 블럭 입니다. 이 초기화 블럭은 주 생성자와 함께 사용되며 init 은 여러개 사용할 수 있습니다. 초기화할 때 로직이 필요한 경우 init 초기화 블록내 로직을 추가하여 초기화 합니다. 조금 더 간단하게 생성자 생성하기 주 생성자 앞에 애노테이션이나 가시성 변경자가 없다면 constructor 는 생략 가능 합니다. 그리고 단순히 주 생성자의 파라미터로 초기화 해줄때는 init 도 생략 가능 합니다. class User ( _nicname:String ) { // 주생성자: constructor 생략 가능     //주 생성자의 파라미터로 초기화, 초기화가 없으면 프로퍼티로도 생성되지 않음,     //getNicname() 함수가 생성 됨     //생성자에서 this.nicname = _nicname 함     val nickname: String = _nicname } 최대한 간략하게 생성자 생성하기 위 코드보다 더 축약이 가능합니다. 주 생성자의 파라미터로 프로퍼티를 초기화하는 경우 생성자 파라미터에 var 또는 val 을 추가하여 간략하게 생성할 수 있습...

코틀린 (Kotlin) 내부 클래스 sealed class 정리

내부 클래스 자바에서 내부 클래스는 바깥쪽 클래스에 대해 참조 를 합니다. 그래서 static class 로 선언하여 바깥쪽 클래스에 대한 참조를 제거할 수 있습니다. 코틀린에서는 기본적으로 static 중첩 클래스 와 같습니다. 그리고 바깥쪽 클래스에 대한 참조를 갖고 싶으면 inner 변경자 를 붙입니다. class Button : View {     override fun getCurrentState(): State {         return ButtonState()     }     //내부 클래스     class ButtonState: State {         fun save() {             getCurrentState() //error! 바깥쪽 참조를 할 수 없다         }     }    //inner class 로 바깥쪽 클래스 참조 가능     inner class ButtonStateInner:State {         fun save() {             getCurrentState() //바깥쪽 클래스 참조 가능         }         fun getOuterReference() {             //this@클래스 로 접근 또는 생략가능         ...

코틀린 (Kotlin) open, final, abstract

코틀린 open 접근자 코틀린의 클래스는 디폴트로 final public 입니다. 그래서 상속을 하려면 open class 이여야 하며 open fun 이여야 합니다. open class RichButton : Clickable {     //interface 는 public 이기 때문에 override 가능     override fun click() {           }     //final 이기때문에 override 불가능     fun disable() {           }     //open 이기때문에 override 가능     open fun animate() {           } } RichButton 의 열려있는 animate() 를 상속한 하위 클래스에서 override 하면서 final 로 제한 할 수 있습니다. open class RichRichButton : RichButton() {     //추가로 final 을 붙이면 하위 클래스에서는 override 할 수 없다     final override fun click() {         super.click()     }     final override fun animate() {         super.animate()     }     final override fun showOff() {       ...

코틀린 (Kotlin) 인터페이스 정리

인터페이스 코틀린의 인터페이스는 자바와 같이 interface 로 시작합니다. interface Clickable {     fun click() } interface 를 구현할 때는 [클래스: 인터페이스] 형식으로 구현됩니다. extends(확장)과 implements(구현) 둘 다 :(콜론) 으로 구현합니다. 코틀린은 1개의 상속과 여러개의 인터페이스를 구현할 수 있습니다. 그리고 override 변경자를 사용해서 자바의 @Override 를 대신합니다. 만약에 override 된 함수 이름과 다른 함수 이름이 중복될경우 둘중 하나는 다른 이름을 사용해야 됩니다. //클래스 상속이나 구현은 : 으로 구분 class Button : Clickable, View { //Clickable은 interface, View 는 상속      override fun click() {           //구현시 override 필수     } } 디폴트 메소드 자바8 에서는 디폴트 메소드인경우 default 를 붙이지만 코틀린에서는 따로 추가되는 변경자가 없이 함수를 구현하면 됩니다. interface Clickable {     fun click()     fun showOff() = Log.d("Clickable showoff") //디폴트 메소드 } 디폴트 메소드는 override 를 하지않은 경우 디폴트로 사용되는 함수 입니다. 같은 함수 이름을 갖는 interface 디폴트 함수 이름이 같은 두개의 인터페이스를 구현해야되는 경우를 생각해봅니다. 디폴트 함수 이름이 같은 이름인 인터페이스를 정의하면 컴파일 에러 가 발생합니다. interface Clickable {     fun click(...

코틀린 (Kotlin) 로컬 함수

코틀린 로컬 함수 코틀린에서 중복 코드를 간단하게 줄일 수 있는 방법으로 로컬 함수 를 사용할 수 있습니다. 로컬 함수는 함수 내부에 함수를 중첩 해서 만들 수 있습니다. 로컬 함수는 바깥 함수의 파라미터 변수에 접근 할 수 있습니다. 그리고 로컬 함수에 파라미터를 전달 하여 사용할 수도 있습니다. class SaveUser {     /**      * 로컬 함수      */     fun validateUser(user: User) {          //로컬 함수는 바깥 함수의 파라미터와 변수에 접근 할 수 있다          fun validate(value: String, fieldName: String) {             if (value.isEmpty()) {                 throw IllegalArgumentException(                     "Can't save user ${user.id}: " +                             "empty $fieldName" + "value=$value")             }     ...

코틀린 (Kotlin) 문자열과 정규식 정리

코틀린 문자열과 정규식 코틀린에서는 자바에는 없는 여러 구분자를 처리할 수 있는 확장함수를 제공합니다. "12.345-6.A".split("\\.|-".toRegex()) //정규식으로 만들어 사용 "12.345-6.A".split(".", "-") //확장 함수로 사용 //결과: [12, 345, 6, A] String 확장 함수 "/document/kotlin/kotlin.txt" 에서 경로와 파일이름, 확장자 를 파싱합니다. 코틀린에서 확장 함수로 제공해주는 함수를 사용하면 정규식 사용없이 손쉽게 문자열을 파싱할 수 있습니다. fun parsePath(path: String ) {         val directory = path. substringBeforeLast ("/")         val fullName = path. substringAfterLast ("/")         val fileName = fullName. substringBeforeLast (".")         val extension = fullName. substringAfterLast (".")         println("Dir: $ directory , name: $ fileName , ext: $ extension ") } 3중 따옴표 문자열 3중 따옴표 문자열에서는 역슬래시(\) 를 포함하여 따로 이스케이프할 필요가 없습니다. 일반적으로 마침표(.) 기호를 이스케이프하려면 \\. 이라고 사용하지만 3중 따옴표 문자열에서는 \. 이라고 사용합니다. fun parsePathRegx(path: String ) {         // """ 으로 묶은 정규표현식은 이스케이프하지 않...

코틀린 (Kotlin) 리스트, 가변 인자, 중위 호출, 구조 분해

코틀린 리스트 코틀린의 리스트는 listOf (...) 으로 생성할 수 있습니다 그리고 setOf (...) 로 Collection 을 생성할 수도 있습니다. val strings: List <String> = listOf("1","2","3") strings. last () //last() 는 확장 함수 val numbers: Collection <Int> = setOf(1,10,100) numbers. max () //max() 는 확장 함수 가변 인자 함수 자바에서는 가변 인자로 'String ...' 을 사용합니다. 코틀린에서는  vararg 변경자를 붙입니다. varag 의 배열을 펼치기 위해서는 *(스프레드) 연산자 를 이용할 수 있습니다 //자바 public static void main( String... args ) { ... } //코틀린 fun main( vararg  values: String ) {     val list = listOf ("list=", *values ) //*연산자가 배열 내용을 펼쳐줍니다     println(list) } main("a","b","c") //"[list=, a, b]" 출력 중위 호출 1 to "one" 처럼 to 를 중간에 사용하는 것을 중위 호출 이라고 합니다. 이때 to 는 일반 메소드 입니다. '객체 메소드이름 유일인자' 사이에는 공백 이 들어가야 합니다. val mapData = mapOf (     1 to "one" ,     //1(객체) to(메소드이름), "one"(유일한 인자)     2 to "two" ,    //to 메소드를 공백으로 ...

코틀린 (Kotlin) 확장 함수와 확장 프로퍼티

코틀린 확장 함수 코틀린는 기존 클래스에 메소드를 추가할 수 있습니다. 이를 확장 함수라고 합니다. 확장 함수는 static 메소드 입니다. 자바의 String 클래스에 lastChar() 라는 메소드를 추가해서 "zerog".lastChar() 처럼 기존 클래스의 메소드인것처럼 사용할 수 있습니다. fun String . lastChar ():Char = this. get ( this . length - 1) //this 생략 가능 fun String . lastChar ():Char = get ( length - 1) String 자바 클래스에는 lastChar() 라는 메소드가 없지만, 확장 함수로 생성해서 String 클래스의 메소드인것처럼 사용합니다. String . lastChar () 중 String 을 수신 객체 타입 (receiver type) 이라고 합니다. lastChar ():Char 중 lastChar () 는 확장 함수의 이름 이고 :Char 는 반환 타입 입니다. this. get (this. length - 1) 중 this 를 수신 객체 (receiver object) 라고 합니다. 확장 함수의 블럭 안에서는 this.get(this.length - 1) 처럼 원래 갖고 있던 메소드를 호출할 수도 있으며 this 는 생략이 가능 합니다. 단, 클래스의 메소드 중 private , protected 접근자인 경우 호출할 수 없습니다 . 확장 함수 이름은 짧게 하는 것이 좋습니다. 제네릭을 이용하면 좀 더 유연한 확장 함수가 됩니다. fun < T > Collection< T >. joinToString (separator: String = "," ,                                 ...

코틀린 (Kotlin) 루프와 예외처리 정리

코틀린 루프문 코틀린의 루프문에는 while, for 가 있습니다 while은 자바와 비슷하기때문에 패스하기로하고 for문에 대해 알아보겠습니다. 코틀린의 for 문에는 in 이 사용됩니다. i in N..M : N 이상 M 이하 범위 지정 i in 0..10 step N : N 만큼 올리거나 내림 i in N downTo M : N부터 M까지 역방향으로 내림 i in N until M : N부터 M 미만까지 for (i in 1..5) {  //1,2,3,4,5  ... } for (i in 5 downTo 1 step 2) { //5,3,1  ... } val list = listOf ("1", "2", "3") for (i in 0 until list.size) {   //"1","2","3"  ... } for (i in 0 .. (list.size-1)) {    //0,1,2  ... } map과 for 반복문 맵에 대한 루프는 for in 으로 간단하게 구현이 가능합니다. 맵에 put 할때는 map[key] = value 로 자바보다 간단하게 사용할 수 있습니다. for in 으로 key, value 를 (key, value)처럼 한번에 뽑아낼 수 있습니다. map 을 key, value로 가져오는것을 구조분해 라고 합니다. val map = TreeMap () for (m in 'A'..'F') {     val b = Integer.toBinaryString(m.toInt())     map[m] = b //map.put(m, b) 과 동일 } //key value 를 뽑을수 있음 for ( (key, value) in map ) { //구조분해 사용      "${key}=${va...

코틀린 (Kotlin) 조건문과 enum, when, 캐스팅 정리

코틀린 enum 코틀린 enum 은 자바의 enum 처럼 사용 가능합니다. 코틀린 enum 은 enum class 입니다. 그리고 프로퍼티와 함수를 선언할 수 있습니다. enum class Color( val r: Int, val g: Int, val b: Int) { //상수 프로퍼티 정의     RED (255,0,0),          //상수 생성시 프로퍼티 값 지정     ORANGE (111,111,111),     GREEN (222,222,222),     BLUE (333,333,333) ; //<- 세미콜린 필수. 구분 역할     fun rgb () = (r * 256 + g) * 256 + b //함수 정의 } Color.BLUE.rgb () //rgb 함수호출 위 코드처럼 상수 프로퍼티를 선언하고 함수를 호출할 수 있습니다. 기억해야될 점은 상수와 함수 사이에 세미콜론(;) 이 꼭 들어가야된다는 것입니다. 코틀린 when 조건문 자바의 switch 문을 코틀린에서는 when 이 대신할 수 있습니다. fun getColorStr (color: Color) =  when (color) {     Color. RED -> "red"     Color. ORANGE -> "orange"     Color. BLUE , Color. GREEN -> "blue and green" // or 임     else -> "unknown" } when 은 switch 처럼 break 가 필요없습니다. 여러 조건을 매칭하고 싶은경우 콤마(,) 으로 구분할 수 있습니다. else 로 조건에 맞지 않을때 행동을 정의할 수 있습니다. fun ge...

코틀린 (Kotlin) 패키지 정리

코틀린 패키지 코틀린의 패키지 구조는 자바와 비슷합니다. 자바와 동일하게 import 로 가져올 수 있으며 클래스와 함수까지 임포트가 가능합니다. 코틀린도 package 로 패키지 경로를 선언합니다. 그리고 클래스 없이 패키지 레벨의 함수도 선언할 수 있습니다. package com.zerogdev.mykotlin.basic.other /**  * 패키지 레벨 함수  */ fun createRandomRectangle () : Rectangle {     val random = Random()     return Rectangle(random.nextInt(), random.nextInt()) } class Test1 { } class Test2 { } 아래 코드는 createRandomRectangle() 의 함수를 임포트했습니다. 그리고 Test1, Test2 클래스를 임포트했습니다. 각 패키지별 클래스와 함수를 따로 임포트되지만, * 을 사용해서 해당 파일 모두를 임포트 할 수 있습니다. package com.zerogdev.mykotlin.basic import com.zerogdev.mykotlin.basic.other.createRandomRectangle import com.zerogdev.mykotlin.basic.other.Test1 import com.zerogdev.mykotlin.basic.other.Test2 import com.zerogdev.mykotlin.basic.other.* //* 사용가능 fun onCreate(savedInstanceState: Bundle?) {     //createRandomRectangle()는 다른 패키지에 있는 함수     createRandomRectangle ().isSquare     val tes...

코틀린 (Kotlin) 클래스와 프로퍼티 정리

코틀린의 클래스 사용 코틀린은 public 이 기본으로 생략 가능 합니다. 코틀린의 클래스 선언은 자바의 멤버변수 선언없이 아래와 같이 사용합니다. class Person ( val name : String, var isCareer : Boolean) 위 코드는 자바에서 Person 클래스안에 String name과 boolean isCareer 멤버변수가 있는것과 같습니다. 프로퍼티 선언 코틀린에서는 자바의 private String name 을  프로퍼티 라고 합니다. class Person (     val name : String,        //읽기 전용 val     var isCareer : Boolean //쓸수있는 var     ) val 프로퍼티 읽기 전용 프로퍼티 private name: String 프로퍼티 생성 public getName() : String 함수 생성 var 프로퍼티 쓰기 가능 프로퍼티 private isCareer: Boolean 프로퍼티 생성 public isCareer() 함수 생성 public setCareer() 함수 생성 코틀린에서 클래스만 생성하면 멤버변수와 setter/getter 가 자동으로 생성되어 아래처럼 바로 사용할 수 있습니다. val person = Person ("zerogdev", true) person. name                 //getter() 사용(자바-> person.getName() ) person. isCareer = false    //setter() 사용(자바-> person.setCareer(false) ) 자바 코드에 setter(), getter() 가 있는경우에는 var 처럼 사용되고 get...

코틀린 (Kotlin) 변수와 문자열 정리

코틀린의 변수 사용 코틀린은 변수 지정시 타입을 생략할 수 있습니다. val text = "hello~" val doubleValue = 2.1e6 초기화를 하지 않을 경우에는 컴파일러가 타입을 추론할 수 없기때문에 변수 선언시 타입을 명시해야 됩니다. val intValue: Int //초기화를 하지않은 경우 타입 명시 필요 intValue = 17    //나중에 초기화 변경 가능한 변수 val(value) 자바의 final 과 동일합니다. 코틀린에서는 기본적으로 val 을 사용해서 불변 변수를 사용하여 함수형 코드로 개발하는 것을 권장합니다. 한 번만 초기화가 가능하므로 아래와 같이 조건에따라 한 번만 초기화 할 수 있습니다. val text : String if (isTrue()) {     text = "true" } else {      text = "false" } var(variable) 값을 대입 후 변경가능하지만 다른 타입을 대입할 수는 없습니다. var message = "message" message = 1234 //컴파일 오류(다른 타입) message = "ok"  //정상 문자열 문자열 내에서 변수에 접근이 가능합니다. 변수 접근 : $변수명 중괄호 사용 : ${ if (조건식) value }                   중괄호 안에서 "" 사용도 가능합니다. 변수만 접근하더라도 중괄호를 사용하여 접근하는 것이 안전합니다. val message = "Hello, kotlin ${ aValue } , $ bValue ,            ${if ( aValue > bValue ) aValue else " b...

코틀린 (Kotlin) 함수 정리

식이 본문인 함수 코틀린은 루프를 제외한 대부분의 제어구조가 식입니다. if, when, try ...와 같은 제어문이 식으로 표현될 수 있습니다. 1. return 에 식으로 대입 할 수 있다. fun max (a: Int, b: Int) : Int {       return if (a > b) a else b } 2. '=' 으로 식을 대입할 수 있습니다. fun max (a: Int, b: Int) : Int = if (a > b) a else b 3. 함수에 반환타입을 생략하면 컴파일러는 리턴 타입을 추론하여 리턴할 수 있습니다. 식이 본문이 함수만 생략가능합니다. fun max (a: Int, b: Int) = if (a > b) a else b 블록이 본문인 함수 중괄호로 둘러 쌓인 함수를 블록이 본문인 함수라고 합니다. 블록인 경우 return 으로 값을 반환해야됩니다.  fun max (a: Int, b: Int) : Int {         if (a > b) {             return a         } else {             return b         }  } 코틀린 함수 - 이름 붙인 인자 함수에 파라메터가 많은 경우 파라메터를 순서에 맞게 잘 넣었는지 혼란스러울 때가 있습니다. 그런경우 코틀린 함수에서는 파라메터 인자에 이름을 붙여 명확하게 사용할 수 있습니다. 함수(파라메터 이름 = 값, 파라메터 이름 = 값, ... ) 처럼 사용할 수 있습니다. 다만, 두번째 파라메터부터 '파라메터 이름 = 값' 을 사용했다면, 이후 뒤에 있는 파라메터들은 모두...