[Android/Kotlin] Android 프로젝트 MainActivity.kt 파일 문법 분석
아래는 Android 프로젝트 생성 시 기본 생성되는 MainActivity.kt 코틀린 파일이다.
package com.example.androidlab
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
Kotlin 문법에 따라 각 구문을 분석해보자.
Package
package com.example.androidlab
코틀린 컴파일러(kotlinc)는 .kt 파일을 컴파일해서 자바 바이트 코드를 만들어 낸다. 코틀린 파일(.kt)을 컴파일하면 자바 클래스(.class) 가 만들어지고 이 클래스 파일이 JVM에서 실행되는 방식이다.
package 구문은 이 파일을 컴파일했을 때 만들어지는 클래스 파일의 위치를 나타낸다. 즉, 위 구문은 MainActivity.kt 파일이 컴파일 되어 생성될 클래스 파일의 위치(디렉터리 경로)를 com/example/androidLab로 지정하는 것이다.
[ ... > com 폴더 > example 폴더 > androidLab 폴더 > MainActivity.class 파일 ]
Import
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
Package에 포함된 클래스나 함수를 해당 파일에서 참조하겠다는 의미.
같은 package로 선언된 파일간의 멤버(변수, 함수, 클래스)는 import문 없이 바로 참조할 수 있다.
위 구문은 android.os패키지의 Bundle클래스, androidx.appcompat.app패키지의 AppCompatActivity 클래스를 import하고 있다. 이렇게 클래스나 메서드를 임포트한다는 건 해당 소스코드 내에서 사용되었거나 사용하겠다는 뜻이다.
실제로 AppCompatActivity는 MainActivity클래스가 상속받는 상위클래스로, Bundle클래스는 onCreate() 메서드의 매개변수 타입으로 MainActivity.kt 파일에 사용되었다. (*클래스 == 타입)
Class
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
일단 클래스 내부 코드는 무시하고 클래스 선언부만을 볼 때, 위 코드는 MainActivity 라는 이름의 클래스를 선언한 뒤, AppCompatActivity라는 클래스를 상속받도록 하고 있다.
하위 클래스를 선언할 때 이름 뒤에 콜론(:)을 입력하고 상속받을 상위 클래스 이름을 입력하면 상속 관계가 되며, 이때 하위 클래스의 생성자에서는 상위 클래스의 생성자를 호출해야 한다. 주 생성자or 보조 생성자 어디에서든 가능하나, 위에서는 하위 클래스의 주생성자에서 바로 상위 클래스의 생성자를 호출했다.
// 하위클래스 주 생성자에서 상위클래스 생성자 호출
class 하위클래스명 : 상위클래스생성자() { }
// 하위클래스 보조 생성자에서 상위클래스 생성자 호출
class 하위클래스명 : 상위클래스명 {
constructor() : 상위클래스생성자() { }
}
AppCompatActivity 클래스를 상속받았기 때문에 MainActivity는 AppCompatActivity클래스 내의 멤버(변수, 함수)를 기본으로 모두 가지게 된다. 참고로 AppCompatActivity도 다른 클래스를 상속받는데, 상속 관계도는 아래와 같다.
Method
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
위에서 말했듯이 MainActivity는 AppCompatActivity를 상속받아 상위 클래스가 가지고 있는 멤버(변수, 함수 등)를 그대로 물려받아 기본적으로 가지고 있게된다. 상위 클래스로부터 상속된 멤버를 하위 클래스에 맞게 재정의해서 사용할 수 있는데 이를 오버라이딩이라 한다. 주로 상위 클래스에 정의된 기능에 새로운 로직을 추가하고 싶을 때 사용한다.
여기서는 onCreate() 메서드가 오버라이딩 되었는데, super.onCreate(savedInstanceState) 구문을 통해 상위 클래스에 정의된 기본의 onCreate() 함수 기능을 그대로 실행 한 뒤 아래에서 추가 로직을 실행하고 있다. 현재 상태로 보면 setContentView() 함수를 추가로 실행하기 위해 onCreate() 함수가 오버라이딩 된 것으로 볼 수 있다.
※ 참고로 onCreate()는 FragmentActivity로 부터, setContentView()는 ComponetnActivity로 부터 상속받은 함수들이다.
즉, 위 코드는 Activity 생성 단계에 상위 클래스의 onCreate() 함수를 한번 실행하고 바로 activity_main 레이아웃을 현재 Activity의 출력 화면으로 정의하도록 하고 있다.
메서드 | 설명 |
onCreate(savedInstanceState: Bundle?) | 이벤트가 발생하면 자동으로 실행되는 콜백 메서드. Activity 생명주기에서 생성 단계에 한번 실행된다. *savedInstanceState : null을 허용하는 Bundle 객체, Activity의 이전 상태를 저장하고 있다. |
setContentView(layoutResID: Int) | 매개변수로 전달받은 레이아웃을 현재 액티비티의 화면으로 정의한다. *layoutRes : 레이아웃 리소스의 ID값 |
※ res 폴더 아래에 리소스를 만들면 자동으로 R.java 파일에 상수 변수(=ResID)로 리소스가 등록된다.