Android 개발을 촉진하는 10가지 Kotlin 기능
게시 됨: 2022-03-11소개
얼마 전 Tomasz는 Android에서 Kotlin 개발을 도입했습니다. 참고로 Kotlin은 가장 인기 있는 Java IDE 중 하나인 IntelliJ IDEA를 개발한 Jetbrains에서 개발한 새로운 프로그래밍 언어입니다. Java와 마찬가지로 Kotlin은 범용 언어입니다. JVM(Java Virtual Machine) 바이트코드를 준수하므로 Java와 함께 사용할 수 있으며 성능 오버헤드가 발생하지 않습니다.
이 기사에서는 Android 개발을 향상하는 데 유용한 상위 10가지 기능을 다룹니다.
참고 : 이 글을 작성할 당시 실제 버전은 Android Studio 2.1.1이었습니다. 코틀린 1.0.2.
코틀린 설정
Kotlin은 JetBrains에서 개발했기 때문에 Android Studio와 IntelliJ 모두에서 잘 지원됩니다.
첫 번째 단계는 Kotlin 플러그인을 설치하는 것입니다. 성공적으로 수행하면 Java를 Kotlin으로 변환하기 위한 새 작업을 사용할 수 있습니다. 두 가지 새로운 옵션은 다음과 같습니다.
- 새 Android 프로젝트를 만들고 프로젝트에서 Kotlin을 설정합니다.
- 기존 Android 프로젝트에 Kotlin 지원을 추가합니다.
새 Android 프로젝트를 만드는 방법을 배우려면 공식 단계별 가이드를 확인하세요. 새로 생성되거나 기존 프로젝트에 Kotlin 지원을 추가하려면 Mac에서 Command + Shift + A
또는 Windows/Linux에서 Ctrl + Shift + A
를 사용하여 찾기 작업 대화 상자 를 열고 프로젝트에서 Configure Kotlin in Project
작업을 호출합니다.
새 Kotlin 클래스를 만들려면 다음을 선택하세요.
-
File
>New
만들기 >Kotlin file/class
또는 -
File
>New
만들기 >Kotlin activity
또는 위에서 언급한 작업을 사용하여 Java 클래스를 만들고 Kotlin으로 변환할 수 있습니다. 클래스, 인터페이스, 열거형 또는 주석을 변환하는 데 사용할 수 있으며 Java를 Kotlin 코드와 쉽게 비교하는 데 사용할 수 있습니다.
많은 타이핑을 줄이는 또 다른 유용한 요소는 Kotlin 확장입니다. 그것들을 사용하려면 모듈 build.gradle
파일에 다른 플러그인을 적용해야 합니다:
apply plugin: 'kotlin-android-extensions'
주의 사항: Kotlin 플러그인 작업을 사용하여 프로젝트를 설정하는 경우 최상위 build.gradle
파일에 다음 코드가 저장됩니다.
buildscript { ext.kotlin_version = '1.0.2' repositories { jcenter() } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } }
이로 인해 확장이 작동하지 않습니다. 이를 수정하려면 해당 코드를 Kotlin을 사용하려는 각 프로젝트 모듈에 복사하기만 하면 됩니다.
모든 것을 올바르게 설정했다면 표준 Android 프로젝트에서와 동일한 방식으로 애플리케이션을 실행하고 테스트할 수 있어야 하지만 이제는 Kotlin을 사용합니다.
Kotlin으로 시간 절약
따라서 Kotlin 언어의 몇 가지 주요 측면을 설명하고 Java 대신 이를 사용하여 시간을 절약할 수 있는 방법에 대한 팁을 제공하는 것으로 시작하겠습니다.
기능 #1: 정적 레이아웃 가져오기
Android에서 가장 일반적인 상용구 코드 중 하나는 findViewById()
함수를 사용하여 활동 또는 조각에서 보기에 대한 참조를 얻는 것입니다.
일부 타이핑을 저장하는 Butterknife 라이브러리와 같은 솔루션이 있지만 Kotlin은 한 번의 가져오기로 레이아웃에서 보기에 대한 모든 참조를 가져올 수 있도록 하여 이를 또 다른 단계로 만듭니다.
예를 들어, 다음 활동 XML 레이아웃을 고려하십시오.
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:andro xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="co.ikust.kotlintest.MainActivity"> <TextView android: android:layout_width="wrap_content" android:layout_height="wrap_content"/> </RelativeLayout>
그리고 함께 제공되는 활동 코드:
package co.ikust.kotlintest import android.support.v7.app.AppCompatActivity import android.os.Bundle import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) helloWorldTextView.text = "Hello World!" } }
정의된 ID가 있는 레이아웃의 모든 보기에 대한 참조를 가져오려면 Android Kotlin 확장 Anko를 사용하세요. 이 import 문을 입력하는 것을 잊지 마십시오:
import kotlinx.android.synthetic.main.activity_main.*
Kotlin에서는 선택 사항이므로 줄 끝에 세미콜론을 작성할 필요가 없습니다.
레이아웃의 TextView
는 보기의 ID와 동일한 이름을 가진 TextView
인스턴스로 가져옵니다. 레이블을 설정하는 데 사용되는 구문을 혼동하지 마십시오.
helloWorldTextView.text = "Hello World!"
우리는 곧 그것을 다룰 것입니다.
주의 사항 :
- 올바른 레이아웃을 가져왔는지 확인하십시오. 그렇지 않으면 가져온 보기 참조가
null
값을 갖습니다. - 프래그먼트를 사용할 때 가져온 View 참조가
onCreateView()
함수 호출 후에 사용되었는지 확인하십시오.onCreateView()
함수에서 레이아웃을 가져오고 View 참조를 사용하여onViewCreated()
에서 UI를 설정합니다.onCreateView()
메서드가 완료되기 전에는 참조가 할당되지 않습니다.
기능 #2: Kotlin으로 POJO 클래스 작성하기
Kotlin으로 가장 많은 시간을 절약할 수 있는 것은 데이터를 보관하는 데 사용되는 POJO(Plain Old Java Object) 클래스를 작성하는 것입니다. 예를 들어 RESTful API의 요청 및 응답 본문에서. RESTful API에 의존하는 애플리케이션에는 이와 같은 클래스가 많이 있습니다.
Kotlin에서는 많은 작업이 수행되며 구문은 간결합니다. 예를 들어 Java에서 다음 클래스를 고려하십시오.
public class User { private String firstName; private String lastName; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } }
Kotlin으로 작업할 때 public 키워드를 다시 작성할 필요가 없습니다. 기본적으로 모든 것은 공개 범위입니다. 예를 들어 클래스를 선언하려면 다음과 같이 작성하면 됩니다.
class MyClass { }
Kotlin에서 위의 Java 코드와 동일합니다.
class User { var firstName: String? = null var lastName: String? = null }
글쎄, 그것은 많은 입력을 저장, 그렇지? Kotlin 코드를 살펴보겠습니다.
Kotlin에서 변수를 정의할 때 두 가지 옵션이 있습니다.
-
var
키워드로 정의되는 가변 변수. -
val
키워드로 정의된 불변 변수.
다음으로 주의할 점은 구문이 Java와 약간 다르다는 것입니다. 먼저 변수 이름을 선언한 다음 유형을 따릅니다. 또한 기본적으로 속성은 null이 아닌 유형이므로 null
값을 허용할 수 없습니다. null
값을 허용하는 변수를 정의하려면 유형 뒤에 물음표를 추가해야 합니다. 나중에 Kotlin에서 이것과 null-safety에 대해 이야기할 것입니다.
주목해야 할 또 다른 중요한 점은 Kotlin에는 클래스에 대한 필드를 선언할 수 있는 기능이 없다는 것입니다. 속성만 정의할 수 있습니다. 따라서 이 경우 firstName
및 lastName
은 기본 getter/setter 메서드가 할당된 속성입니다. 언급했듯이 Kotlin에서는 기본적으로 둘 다 공개되어 있습니다.
사용자 지정 접근자는 다음과 같이 작성할 수 있습니다.
class User { var firstName: String? = null var lastName: String? = null val fullName: String? get() firstName + " " + lastName }
외부에서 구문과 관련하여 속성은 Java의 공개 필드처럼 작동합니다.
val userName = user.firstName user.firstName = "John"
새 속성 fullName
은 읽기 전용이며( val
키워드로 정의됨) 사용자 지정 getter가 있습니다. 단순히 이름과 성을 추가합니다.
Kotlin의 모든 속성은 선언되거나 생성자에 있을 때 할당되어야 합니다. 그것이 편리하지 않은 경우가 있습니다. 예를 들어 종속성 주입을 통해 초기화되는 속성의 경우입니다. 이 경우 lateinit
modifier를 사용할 수 있습니다. 다음은 예입니다.
class MyClass { lateinit var firstName : String; fun inject() { firstName = "John"; } }
속성에 대한 자세한 내용은 공식 문서에서 확인할 수 있습니다.
기능 #3: 클래스 상속과 생성자
Kotlin은 생성자에 관해서도 더 간결한 구문을 가지고 있습니다.
생성자
Kotlin 클래스에는 기본 생성자와 하나 이상의 보조 생성자가 있습니다. 기본 생성자를 정의하는 예:
class User constructor(firstName: String, lastName: String) { }
기본 생성자는 클래스 정의에서 클래스 이름 뒤에 옵니다. 기본 생성자에 주석이나 가시성 수정자가 없으면 생성자 키워드를 생략할 수 있습니다.
class Person(firstName: String) { }
기본 생성자는 코드를 가질 수 없습니다. 모든 초기화는 init
코드 블록에서 수행되어야 합니다.
class Person(firstName: String) { init { //perform primary constructor initialization here } }
또한 기본 생성자를 사용하여 속성을 정의하고 초기화할 수 있습니다.
class User(var firstName: String, var lastName: String) { // ... }
일반 속성과 마찬가지로 기본 생성자에서 정의된 속성은 변경할 수 없거나( val
) 변경할 수 있습니다( var
).
클래스에는 보조 생성자가 있을 수도 있습니다. 하나를 정의하는 구문은 다음과 같습니다.
class User(var firstName: String, var lastName) { constructor(name: String, parent: Person) : this(name) { parent.children.add(this) } }
모든 보조 생성자는 기본 생성자에게 위임해야 합니다. 이것은 this
키워드를 사용하는 Java와 유사합니다.
class User(val firstName: String, val lastName: String) { constructor(firstName: String) : this(firstName, "") { //... } }
클래스를 인스턴스화할 때 Kotlin에는 Java처럼 new
키워드가 없습니다. 앞서 언급한 User
클래스를 인스턴스화하려면 다음을 사용하십시오.
val user = User("John", "Doe)
상속 소개
Kotlin에서 모든 클래스는 Java의 Object
와 유사한 Any
에서 확장됩니다. 기본적으로 클래스는 Java의 최종 클래스와 같이 닫힙니다. 따라서 클래스를 확장하려면 open
또는 abstract
로 선언해야 합니다.
open class User(val firstName, val lastName) class Administrator(val firstName, val lastName) : User(firstName, lastName)
Java의 새 클래스 생성자에서 super()
메서드를 호출하는 것과 유사한 확장 클래스의 기본 생성자에 위임해야 합니다.
수업에 대한 자세한 내용은 공식 문서를 확인하세요.
기능 #4: 람다 표현식
Java 8에 도입된 Lambda 표현식은 Java 8에서 가장 선호하는 기능 중 하나입니다. 그러나 Android는 여전히 Java 7만 지원하고 Java 8은 곧 지원되지 않을 것으로 보이기 때문에 상황이 그리 밝지 않습니다. 따라서 Retrolambda와 같은 해결 방법은 람다 식을 Android로 가져옵니다.
Kotlin을 사용하면 추가 라이브러리나 해결 방법이 필요하지 않습니다.
코틀린의 함수
Kotlin의 함수 구문부터 빠르게 살펴보겠습니다.
fun add(x: Int, y: Int) : Int { return x + y }
함수의 반환 값은 생략할 수 있으며 이 경우 함수는 Int
를 반환합니다. Kotlin의 모든 것은 Any
에서 확장된 객체이며 기본 유형이 없다는 것을 반복할 가치가 있습니다.
함수의 인수는 기본값을 가질 수 있습니다. 예를 들면 다음과 같습니다.
fun add(x: Int, y: Int = 1) : Int { return x + y; }
이 경우 x
인수만 전달하여 add()
함수를 호출할 수 있습니다. 동등한 Java 코드는 다음과 같습니다.
int add(int x) { Return add(x, 1); } int add(int x, int y) { return x + y; }
함수를 호출할 때 또 다른 좋은 점은 명명된 인수를 사용할 수 있다는 것입니다. 예를 들어:
add(y = 12, x = 5)
기능에 대한 자세한 내용은 공식 문서를 확인하십시오.
Kotlin에서 람다 표현식 사용
Kotlin의 람다 표현식은 Java에서 익명 함수로 볼 수 있지만 구문이 더 간결합니다. 예를 들어 자바와 코틀린에서 클릭 리스너를 구현하는 방법을 보여드리겠습니다.
자바에서:
view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(v.getContext(), "Clicked on view", Toast.LENGTH_SHORT).show(); } };
코틀린:
view.setOnClickListener({ view -> toast("Click") })
와! 단 한 줄의 코드! 람다 표현식이 중괄호로 둘러싸여 있음을 알 수 있습니다. 매개변수가 먼저 선언되고 본문이 ->
기호 뒤에 옵니다. 클릭 리스너를 사용하면 유추할 수 있으므로 보기 매개변수의 유형이 지정되지 않습니다. 본문은 단순히 Kotlin이 제공하는 토스트를 표시하기 위한 toast()
함수에 대한 호출입니다.

또한 매개변수가 사용되지 않는 경우 생략할 수 있습니다.
view.setOnClickListener({ toast("Click") })
Kotlin은 Java 라이브러리를 최적화했으며 인수에 대해 하나의 메서드가 있는 인터페이스를 수신하는 모든 함수는 인터페이스 대신 함수 인수를 사용하여 호출할 수 있습니다.
또한 함수가 마지막 매개변수인 경우 괄호 밖으로 이동할 수 있습니다.
view.setOnClickListener() { toast("Click") }
마지막으로, 함수에 함수인 매개변수가 하나만 있는 경우 괄호를 생략할 수 있습니다.
view.setOnClickListener { toast("Click") }
자세한 내용은 Antonio Leiva의 Android 개발자용 Kotlin 책과 공식 문서를 확인하세요.
확장 기능
C#과 유사한 Kotlin은 확장 기능을 사용하여 기존 클래스를 새로운 기능으로 확장하는 기능을 제공합니다. 예를 들어 String
의 MD5 해시를 계산하는 확장 메서드는 다음과 같습니다.
fun String.md5(): ByteArray { val digester = MessageDigest.getInstance("MD5") digester.update(this.toByteArray(Charset.defaultCharset())) return digester.digest() }
함수 이름 앞에는 확장 클래스의 이름(이 경우 String
)이 오고 확장 클래스의 인스턴스는 this
키워드를 통해 사용할 수 있습니다.
확장 기능은 Java 유틸리티 기능과 동일합니다. Java의 예제 함수는 다음과 같습니다.
public static int toNumber(String instance) { return Integer.valueOf(instance); }
예제 함수는 유틸리티 클래스에 배치해야 합니다. 이것이 의미하는 바는 확장 함수가 원래 확장 클래스를 수정하지 않지만 유틸리티 메소드를 작성하는 편리한 방법이라는 것입니다.
기능 #5: Null 안전
Java에서 가장 많은 노력을 기울이는 것 중 하나는 아마도 NullPointerException
일 것입니다. Null-safety는 Kotlin 언어에 통합된 기능이며 일반적으로 걱정할 필요가 없을 정도로 암시적입니다. 공식 문서에 따르면 NullPointerExceptions
의 가능한 원인은 다음과 같습니다.
-
NullPointerException
을 던지기 위한 명시적 호출. - 를 사용하여
!!
연산자(나중에 설명하겠습니다). - 외부 자바 코드.
- 초기화되기 전에 생성자에서
lateinit
속성에 액세스하면UninitializedPropertyAccessException
이 발생합니다.
기본적으로 Kotlin의 모든 변수와 속성은 명시적으로 nullable로 선언되지 않은 경우 null이 non-null
것으로 간주됩니다( null
값을 보유할 수 없음). 이미 언급했듯이 null
값을 허용하는 변수를 정의하려면 유형 뒤에 물음표를 추가해야 합니다. 예를 들어:
val number: Int? = null
그러나 다음 코드는 컴파일되지 않습니다.
val number: Int? = null number.toString()
컴파일러가 null
검사를 수행하기 때문입니다. 컴파일하려면 null
검사를 추가해야 합니다.
val number: Int? = null if(number != null) { number.toString(); }
이 코드는 성공적으로 컴파일됩니다. 이 경우 백그라운드에서 Kotlin이 하는 일은 if 블록 내에서 해당 number
가 nun-null
( Int
대신 Int?
)이 되는 것입니다.
안전한 호출 연산자 ( ?.
)를 사용하여 null
검사를 단순화할 수 있습니다.
val number: Int? = null number?.toString()
두 번째 줄은 숫자가 null
이 아닌 경우에만 실행됩니다. 유명한 Elvis 연산자 ( ?:
)를 사용할 수도 있습니다.
val number Int? = null val stringNumber = number?.toString() ?: "Number is null"
?:
왼쪽의 표현식이 null
이 아니면 평가되어 반환됩니다. 그렇지 않으면 오른쪽 표현식의 결과가 반환됩니다. 또 다른 깔끔한 점은 Elvis 연산자의 오른쪽에 throw
또는 return
을 사용할 수 있다는 것입니다. 이는 Kotlin의 표현식이기 때문입니다. 예를 들어:
fun sendMailToUser(user: User) { val email = user?.email ?: throw new IllegalArgumentException("User email is null") //... }
!! 운영자
Java에서와 같은 방식으로 NullPointerException
을 발생시키려면 !!
운영자. 다음 코드는 NullPointerException
을 발생시킵니다.
val number: Int? = null number!!.toString()
주조
as
키워드를 사용하여 캐스팅 완료:
val x: String = y as String
이것은 "안전하지 않은" 캐스팅으로 간주됩니다. Java처럼 캐스트가 불가능한 경우 ClassCastException
이 발생하기 때문입니다. 예외를 throw하는 대신 null
값을 반환하는 "안전한" 캐스트 연산자가 있습니다.
val x: String = y as? String
캐스팅에 대한 자세한 내용은 공식 문서의 Type Casts 및 Casts 섹션을 확인하고, null
안전에 대한 자세한 내용은 Null-Safety 섹션을 확인하세요.
lateinit
속성
lateinit
속성을 사용하면 NullPointerException
과 유사한 예외가 발생할 수 있습니다. 다음 클래스를 고려하십시오.
class InitTest { lateinit var s: String; init { val len = this.s.length } }
이 코드는 경고 없이 컴파일됩니다. 그러나 TestClass
의 인스턴스가 생성되자마자 초기화되기 전에 속성 s
에 액세스하기 때문에 UninitializedPropertyAccessException
이 발생합니다.
기능 #6: 함수 with()
with()
함수는 유용하며 Kotlin 표준 라이브러리와 함께 제공됩니다. 개체의 많은 속성에 액세스해야 하는 경우 일부 입력을 저장하는 데 사용할 수 있습니다. 예를 들어:
with(helloWorldTextView) { text = "Hello World!" visibility = View.VISIBLE }
객체와 확장 기능을 매개변수로 받습니다. 코드 블록(중괄호 안)은 첫 번째 매개변수로 지정된 개체의 확장 기능에 대한 람다 식입니다.
기능 #7: 연산자 오버로딩
Kotlin을 사용하면 미리 정의된 연산자 집합에 대해 사용자 지정 구현을 제공할 수 있습니다. 연산자를 구현하려면 지정된 이름의 멤버 함수 또는 확장 함수를 제공해야 합니다.
예를 들어, 곱하기 연산자를 구현하려면 이름이 times(argument)
인 멤버 함수 또는 확장 함수를 제공해야 합니다.
operator fun String.times(b: Int): String { val buffer = StringBuffer() for (i in 1..b) { buffer.append(this) } return buffer.toString() }
위의 예는 String
에 대한 이진 *
연산자의 구현을 보여줍니다. 예를 들어 다음 표현식은 "TestTestTestTest" 값을 newString
변수에 할당합니다.
val newString = "Test" * 4
확장 기능을 사용할 수 있으므로 모든 개체에 대한 연산자의 기본 동작을 변경할 수 있습니다. 이것은 양날의 검이므로 주의해서 사용해야 합니다. 오버로드될 수 있는 모든 연산자의 함수 이름 목록은 공식 문서를 확인하세요.
Java와 비교한 또 다른 큰 차이점은 ==
및 !=
연산자입니다. 연산자 ==
번역:
a?.equals(b) ?: b === null
동안 연산자 !=
는 다음과 같이 번역됩니다.
!(a?.equals(b) ?:
이것이 의미하는 바는 ==
를 사용하면 Java에서와 같이 ID 검사가 수행되지 않지만(객체의 인스턴스가 동일한지 비교) null
검사와 함께 equals()
메서드와 동일한 방식으로 작동합니다.
ID 확인을 수행하려면 Kotlin에서 ===
및 !==
를 사용해야 합니다.
기능 #8: 위임된 속성
특정 속성은 몇 가지 일반적인 동작을 공유합니다. 예를 들어:
- 처음 액세스할 때 초기화되는 지연 초기화 속성입니다.
- Observer 패턴에서 Observable을 구현하는 속성입니다.
- 별도의 필드로 대신 맵에 저장되는 속성입니다.
이와 같은 경우를 더 쉽게 구현하기 위해 Kotlin은 Delegated Properties 를 지원합니다.
class SomeClass { var p: String by Delegate() }
이것은 속성 p
에 대한 getter 및 setter 함수가 다른 클래스인 Delegate
의 인스턴스에 의해 처리됨을 의미합니다.
String
속성에 대한 대리자의 예:
class Delegate { operator fun getValue(thisRef: Any?, property: KProperty<*>): String { return "$thisRef, thank you for delegating '${property.name}' to me!" } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { println("$value has been assigned to '${property.name} in $thisRef.'") } }
위의 예는 속성이 할당되거나 읽을 때 메시지를 인쇄합니다.
대리자는 변경 가능한( var
) 속성과 읽기 전용( val
) 속성 모두에 대해 만들 수 있습니다.
읽기 전용 속성의 경우 getValue
메서드를 구현해야 합니다. 두 개의 매개변수가 필요합니다(공식 문서에서 가져옴).
- 수신기 - 속성 소유자와 동일하거나 상위 유형이어야 합니다(확장 속성의 경우 확장되는 유형임).
- 메타데이터 -
KProperty<*>
유형 또는 상위 유형이어야 합니다.
이 함수는 속성 또는 해당 하위 유형과 동일한 유형을 반환해야 합니다.
변경 가능한 속성의 경우 대리자는 다음 매개 변수를 사용하는 setValue
라는 함수를 추가로 제공해야 합니다.
- 수신기 -
getValue()
와 동일합니다. - 메타데이터 -
getValue()
와 동일합니다. - 새 값 - 속성 또는 해당 상위 유형과 동일한 유형이어야 합니다.
가장 일반적인 상황을 다루는 몇 가지 표준 대리자가 Kotlin과 함께 제공됩니다.
- 게으른
- 주목할 만한
- 거부권
게으른
Lazy는 람다 식을 매개 변수로 사용하는 표준 대리자입니다. 전달된 람다 표현식은 getValue()
메소드가 처음 호출될 때 실행됩니다.
기본적으로 지연 속성 평가는 동기화됩니다. 다중 스레딩에 관심이 없다면 lazy(LazyThreadSafetyMode.NONE) { … }
를 사용하여 추가 성능을 얻을 수 있습니다.
주목할 만한
Delegates.observable()
은 Observer 패턴에서 Observable로 동작해야 하는 속성을 위한 것입니다. 초기 값과 세 개의 인수(속성, 이전 값 및 새 값)가 있는 함수라는 두 개의 매개변수를 허용합니다.
주어진 람다 표현식은 setValue()
메소드가 호출될 때마다 실행됩니다:
class User { var email: String by Delegates.observable("") { prop, old, new -> //handle the change from old to new value } }
거부권
이 표준 대리자는 속성에 할당된 새 값을 저장할지 여부를 결정할 수 있는 특별한 종류의 Observable입니다. 값을 할당하기 전에 몇 가지 조건을 확인하는 데 사용할 수 있습니다. Delegates.observable()
과 마찬가지로 초기 값과 함수라는 두 가지 매개변수를 받습니다.
차이점은 함수가 부울 값을 반환한다는 것입니다. true
를 반환하면 속성에 할당된 새 값이 저장되거나 삭제됩니다.
var positiveNumber = Delegates.vetoable(0) { d, old, new -> new >= 0 }
주어진 예제는 속성에 할당된 양수만 저장합니다.
자세한 내용은 공식 문서를 확인하세요.
기능 #9: 지도에 개체 매핑
일반적인 사용 사례는 지도 내부에 속성 값을 저장하는 것입니다. 이는 RESTful API와 함께 작동하고 JSON 객체를 구문 분석하는 애플리케이션에서 자주 발생합니다. 이 경우 지도 인스턴스를 위임된 속성의 대리자로 사용할 수 있습니다. 공식 문서의 예:
class User(val map: Map<String, Any?>) { val name: String by map val age: Int by map }
이 예에서 User
에는 지도를 사용하는 기본 생성자가 있습니다. 두 속성은 속성 이름과 동일한 키 아래에 매핑된 맵에서 값을 가져옵니다.
val user = User(mapOf( "name" to "John Doe", "age" to 25 ))
새 사용자 인스턴스의 name 속성에는 "John Doe" 값이 할당되고 age 속성에는 값 25가 할당됩니다.
이것은 MutableMap
과 함께 var 속성에서도 작동합니다.
class MutableUser(val map: MutableMap<String, Any?>) { var name: String by map var age: Int by map }
기능 #10: 컬렉션 및 기능적 작업
Kotlin의 람다 지원으로 컬렉션을 새로운 차원으로 활용할 수 있습니다.
우선 Kotlin은 변경 가능한 컬렉션과 변경할 수 없는 컬렉션을 구분합니다. 예를 들어 Iterable 인터페이스에는 두 가지 버전이 있습니다.
- 반복 가능
- 변경 가능 반복 가능
Collection , List , Set 및 Map 인터페이스도 마찬가지입니다.
예를 들어 다음 any
연산은 하나 이상의 요소가 주어진 술어와 일치하는 경우 true
를 반환합니다.
val list = listOf(1, 2, 3, 4, 5, 6) assertTrue(list.any { it % 2 == 0 })
컬렉션에서 수행할 수 있는 기능적 작업의 광범위한 목록은 이 블로그 게시물을 확인하세요.
결론
우리는 Kotlin이 제공하는 것의 표면을 긁었습니다. 더 읽고 더 배우고 싶은 사람들은 다음을 확인하십시오.
- Antonio Leiva의 Kotlin 블로그 게시물 및 책입니다.
- JetBrains의 공식 문서 및 자습서.
요약하자면 Kotlin은 직관적이고 간결한 구문을 사용하여 기본 Android 애플리케이션을 작성할 때 시간을 절약할 수 있는 기능을 제공합니다. 아직 어린 프로그래밍 언어지만 제 생각에는 이제 프로덕션 앱을 빌드하는 데 사용할 수 있을 정도로 안정적입니다.
Kotlin 사용의 이점:
- Android Studio의 지원은 원활하고 우수합니다.
- 기존 Java 프로젝트를 Kotlin으로 쉽게 변환할 수 있습니다.
- Java 및 Kotlin 코드는 동일한 프로젝트에 공존할 수 있습니다.
- 애플리케이션에는 속도 오버헤드가 없습니다.
단점:
- Kotlin은 생성된
.apk
에 라이브러리를 추가하므로 최종.apk
크기는 약 300KB가 됩니다. - 남용할 경우 연산자 오버로딩으로 인해 읽을 수 없는 코드가 생성될 수 있습니다.
- IDE 및 자동 완성은 순수한 Java Android 프로젝트에서보다 Kotlin으로 작업할 때 약간 느리게 작동합니다.
- 컴파일 시간이 조금 더 길어질 수 있습니다.