IntelliJ에서의 코틀린 프로그래밍 - 프로퍼티 (2)

업데이트:

  • 연구주제 : 코틀린 프로그래밍
  • 연구목적 : 안드로이드에서의 코틀린 활용
  • 연구일시 : 2020년 02월 14일 09:00~17:00
  • 연구자 : 이재환 ljh951103@naver.com
  • 연구장비 : HP EliteDesk 800 G4 TWR, Kotlin, Android studio, IntelliJ
  • 관련연구 : Java, Android, Kotlin, IntelliJ


서론

이번 시간에도 코틀린에서의 프로퍼티에 대해 남은 내용에 대해 알아보도록 하겠다.


본론

정적 변수와 컴패니언 객체

정적 변수를 사용하기위해 자바에서는 static 키워드를 사용했는데 코틀린에서는 이 키워드가 존재하지않는다.
코틀린은 컴패니언 객체를 정적변수의 대체제로 사용한다.

class Person {
    var name: String = "JaeHwan"
    companion object {
        var language: String = "Korean"
        fun work( ) {
            println("Working")
        }
    }
}

fun main( ) {
    println(Person.language)
    Person.language = "English"
    Person.work( )
}

위의 예를 보면 companion 객체의 범위 안에 있는 코드들은 다음과 같이 객체 생성없이도 접근할 수 있고, 값을 변경할 수도 있다.

  • 코틀린에서 자바 static 멤버와 연동하기

코틀린와 자바를 함께 사용하는 경우가 많다. 그렇다면 자바의 static 멤버 변수에 어떻게 접근할 수 있을까?

public class Customer {}
.. Java code ..
}
fun main( ) {
    println(Customer.LEVEL)
    Customer.login
}

이런식으로 자바의 스태틱 메소드나 변수에도 손쉽게 접근할 수 있다.

그럼 자바에서도 코틀린 객체를 사용할 수 있을까?

class KCustomer {
    companion object {
        const val LEVEL = " "
        @JVMStatic fun login( ) = println("Login...")
    }
}
...
System.out.println(KCustomer.LEVEL);
KCustomer.login( );   @JvmStatic 사용했을 
KCustomer.Companion.login( );   // @JvmStatic 사용하지 않았을 떄
...
  • const는 컴파일 시간의 상수다. 자바에서 접근하기 위해 필요하다.
  • @JVMStatic 애노티에션은 자바에서 코드를 해석할 때 Companion을 생략할 수 있게 해준다.

마찬가지로 자바에서 프로퍼티를 사용하고자 할 경우네는 @JvmField 애노테이션을 사용할 수 있다.


  • 최상위 함수 사용
@file:JvmName("PKLevel")
fun packageLevelFunc( ){
    println("Package-Level Function")
}

fun main( ) {
    packageLevelFunc( )
}

위의 함수는 우리가 계속 써오던 방식이다. 이것은 객체없이 어떻게 실행되는 걸까?
최상위함수인 packageLevelFunc( ) 함수는 역 커패일 해보았을 때 static으로 선언되어 있다.
그리고 packageLevelFunctionKt 클래스가 자동으로 생성되어있음을 확인할 수 있다.

우리는 다음과 같은 코드로 이 클래스의 이름을 지정해줄 수 있다.

@file:JvmName("PKLevel")
fun packageLevelFunc( ){
    println("Package-Level Function")
}

fun main( ) {
    packageLevelFunc( )
}

역시나 내부적으로 static으로 선언되어 있기 때문에 main( ) 블록에서 객체없이 사용할 수 있고 자바에서도 정적 함수처럼 접근이 가능하다.


  • object, 싱글톤

하위 클래스를 생성하지 않고 내용이 조금 변경된 클래스를 만들어야 할 때, 자바에서는 익명 내부 클래스를 만들어서 처리할 수 있다.
코틀린에서는 그 기능을 object 표현식이나 선언으로 쉽게 처리할 수 있다.

// object 키워드를 사용한 방식
object OCustomer {
    var name = "Jaehwan"
    fun greeting ( ) = println("Hello world")
    val HOBBY = Hobby("Basketball")
}

// 컴패니언 객체를 사용한 방식
class CCusomer {
    const val HELLO = "hello"
    var name = "Jaehwan"
    @JvmField val HOBBY = Hobby("Football")
    @JvmStatic fun greeting( ) = println("Hello world")
}

다음 코드를 보면 object로 선언된 클래스는 객체 생성없이 이름의 점(.) 표기법으로 바로 사용할 수 있다. 싱글톤 패턴에 이용된다.

이 방식을 사용하면 접근 시점에 객체가 생성된다. 따라서 생성자를 사용할 수 없지만 초기화 블록인 init은 들어갈 수 있다. 물론 클래스나 인터페이스를 상속할 수는 있다.
그렇다면 자바에서 object 선언으로의 접근은 어떻게 이루어질까?

OCustomer.INSTANCE.getName( );

다음과 같이 INSTANCE를 통해 멤버에 접글할 수 있다.


  • object 표현식

object 표현식은 선언과 달리 이름이 없으며 싱글톤이 아니다.
따라서 object 표현식이 사용될 때마다 새로운 인스턴스가 생성된다.
결과적으로 이름이 없는 익명 내부 클래스의 형태를 이 표현법을 통해 만들 수 있다.

open class Superman( ){
    open fun fly( ) = println("Flying in the air.")
}

fun main( ) {
    val pretendedMan = object: Superman( ) {   // object 표현식으로 구현의 재정의
        override fun fly( ) = print("I can't fly!")
    }
    pretendedMan.work( )
    pretendedMan.talk( )
    pretendedMan.fly( )
}

다음과 같이 fly( ) 메소드를 오버라이딩하여 사용할 수 있다.

딱 한 번만 구현되는 인터페이스 구현 클래스를 정의하기가 부담으러운 경우 다음과 같이 사용할 수 있다.

interface Shape {
    fun onDraw( )   // 구현해야 할 메소드
}

val triangle = object: Shape {
    override fun onDraw( ) {   // 딱 한번 구현
        ...
    }
}

객체는 필요하지만 상위 인터페이스나 클래스가 없는 경우 다음과 같이 사용할 수 있다.

fun foo( ) {
    val adHoc = object {
        var x: Int = 0
        var y: Int = 0
    }
    print(adHoc.x + adHoc.y)
}

이런 익명 객체는 지역이나 private 정의 영역에서만 사용할 수 있다.

class C {
    private fun foo( ) = object {   // 반환자료형은 익명 객체 자료형
        val x: String = "x"
    }

    fun publicFoo( ) = object {   // 반환 자료형은 Any
        val x: String = "x"
    }

    fun bar( ) {
        val x1 = foo( ).x   // 정상동작
        val x2 = publicFoo( ).x // 오류
    }
}

자바의 익명 내부 클래스와 같이, object 표현식 안의 코드는 둘러쌓인 범위 외부의 변수에 접근할 수 있다.


결론

코틀린의 프로퍼티에 대해 마저 알아보았다. 정적변수를 표현함에 있어서 코틀린만의 장점을 지닌 컴패니언 객체나, object 선언 및 표기법이 있었다.


향후과제

다양한 클래스와 인터페이스


참고자료

Do it! 코틀린 프로그래밍 (이지스퍼블리싱)
https://book.naver.com/bookdb/book_detail.nhn?bid=15000572


Writer: Jae-Hwan Lee

댓글남기기