public static main in Kotlin
12 Apr 2019 | Kotlin코틀린에서는 Java의 static main 함수를 다음과 같이 작성할 수 있습니다.
Main.kt
fun main(args: Array<String>) {
println("Hello, Kotlin")
}
코틀린에서는 Java의 static main 함수를 다음과 같이 작성할 수 있습니다.
fun main(args: Array<String>) {
println("Hello, Kotlin")
}
dependencies {
implementation 'com.android.support:design:28.0.0'
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/add_log_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add Log"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
app:cardCornerRadius="4dp"
app:cardElevation="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:orientation="vertical">
<TextView
android:id="@+id/message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="8dp"
android:text="message"
android:textColor="@android:color/holo_blue_dark"
android:textSize="14sp"/>
<TextView
android:id="@+id/timestamp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:text="timestamp"
android:textColor="@android:color/darker_gray"
android:textSize="10sp"/>
</LinearLayout>
</android.support.v7.widget.CardView>
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.TextView
data class LogItem(val text: String, val timestamp: String)
class LogListAdapter(val ctx: Context) : BaseAdapter() {
private val list = ArrayList<LogItem>()
init {
list.add(LogItem("hello", "2019/04/15 13:00"))
list.add(LogItem("Nice to meet you", "2019/04/15 14:00"))
list.add(LogItem("Good bye", "2019/04/15 17:00"))
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
var view: View
val holder: ViewHolder
if (convertView == null) {
view = LayoutInflater.from(ctx).inflate(R.layout.item_log, parent, false)
holder = ViewHolder()
holder.message = view.findViewById(R.id.message)
holder.timestamp = view.findViewById(R.id.timestamp)
view.tag = holder
} else {
view = convertView
holder = convertView.tag as ViewHolder
}
val item = list[position]
holder.message.text = item.text
holder.timestamp.text = item.timestamp
return view
}
override fun getItem(position: Int): LogItem {
return list[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getCount(): Int {
return list.size
}
}
private class ViewHolder {
lateinit var message: TextView
lateinit var timestamp: TextView
}
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)
val adapter = LogListAdapter(applicationContext)
listview.adapter = adapter
}
}
buildscript {
ext.kotlin_version = '1.3.21'
ext.anko_version='0.10.8'
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.anko:anko:$anko_version"
}
코틀린에서는 Java에서와 달리 interface 내부의 함수가 내용을 가질 수도 있고, abstract 멤버 변수를 가질 수도 있습니다.
또한 Java에서는 implements 키워드를 이용해서 인터페이스를 구현했는데, 코틀린에서는 상속과 마찬가지로 콜론(:)을 사용해서 인터페이스를 구현할 수 있습니다.
interface OnEventListener {
open fun onEvent(type: Int)
}
open class EventHandler(var name: String) : OnEventListener {
override fun onEvent(type: Int) {
TODO("not implemented")
}
}
아래 예제는 하나의 클래스가 여러 개의 인터페이스를 구현한 예제입니다. 인터페이스 내의 함수들이 구현체가 있고, 중복된 함수가 있을 경우 구현한 클래스에서는 필요한 클래스의 super를 호출할 수 있습니다. 둘 다 호출해도 상관없고, 필요한 super만 호출해도 상관없습니다.
interface onEventListener {
fun onEvent() {}
fun onMessageArrived() {}
}
interface onClientEventListener {
fun onEvent() {}
fun onConnected() {}
fun onDisconnected() {}
}
class TcpServer : onEventListener, onClientEventListener {
override fun onEvent() {
super<onEventListener>.onEvent()
super<onClientEventListener>.onEvent()
}
}
코틀린에서 상속 받을 때는 : 기호를 이용해서 상속 받습니다. 그리고 부모 클래스는 open 이나 abstract 키워드를 사용해야만 상속할 수 있습니다.
그리고 기본적으로 모든 클래스는 Java에서의 Object 처럼 Any라는 클래스를 상속받고 있습니다.
open class Shape(vertex: Int) {
open fun onDraw(canvas: Canvas) {
}
}
class Triangle() : Shape(3) {
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
TODO("Draw Lines")
}
}
class Rectangle() : Shape(4) {
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
TODO("Draw Lines")
}
}
open 키워드를 사용하지 않은 경우는 코틀린에서 기본적으로 final로 선언됩니다. 즉 오버라이드를 하고 싶으면 반드시 open을 붙여야 합니다.
부모 클래스의 생성자가 여러 개인 경우 상속받는 자식 클래스는 다음과 같이 작성할 수 있습니다.
class CustomDialog(ctx: Context) : AlertDialog(ctx) {
}
또는
class CustomDialog : AlertDialog {
constructor(ctx: Context) : super(ctx)
}
와 같이 작성할 수 있습니다. 이 경우 두 번째 방법이 더 좋습니다.
첫 번째 방법의 경우 부모 클래스의 디폴트 생성자가 정해져 있어서 다른 생성자를 만들기 어렵습니다.
만약 다음과 같이 코드를 작성하면 Primary constructor call expected 오류가 발생합니다.
class CustomDialog(ctx: Context) : AlertDialog(ctx) {
constructor(ctx: Context, themeId: Int) : super(ctx, themeId)
}
두 번째 방법으로 사용하면 다음과 같이 해결할 수 있습니다.
class CustomDialog : AlertDialog {
constructor(ctx: Context) : super(ctx, android.R.style.Theme_NoTitleBar)
constructor(ctx: Context, themeId: Int) : super(ctx, themeId)
}