[Android/Flutter 교육] 8일차

MSU·2024년 1월 5일

Android-Flutter

목록 보기
8/85
post-thumbnail

코틀린 교육이 끝나고 과제 평가가 있을 예정(프로젝트폴더 압축파일제출)
오늘까지 배운 내용을 토대로 문제가 나옴

클래스 상속 복습

  • A 클래스 (부모)
    변수 a
    메서드 a
  • B 클래스 (자식)
    변수 b
    메서드 b

B클래스가 A클래스를 상속받고
B타입의 변수 b1에 B클래스의 인스턴스를 담으면 -> 변수 a,b, 메서드 a,b 모두 사용 가능
A타입의 변수 a1에 B클래스의 인스턴스를 담으면 -> 변수 a, 메서드 a 만 사용 가능

오버라이딩 복습

자식클래스(B)에서 부모클래스(A)의 메서드를 오버라이딩하고 추후 생성한 자식클래스 객체에서 해당 메서드를 호출하면 부모클래스의 메서드가 아닌 자식클래스의 메서드가 호출됨
오버라이딩을 안한 경우에는 원래대로 부모클래스(A)의 메서드가 호출됨
부모클래스의 메서드 내용을 호출하고 싶으면 super를 통해 접근가능

    override fun superMethod2(){
        // 만약 부모의 메서드를 호출하고자 한다면 super를 통해 접근한다.
        super.superMethod2()
        
        println("SubClass1의 superMethod2")
    }

안드로이드OS(과거시점)
안드로이드APP(미래시점)
프로그램마다 동작하는 코드가 다름
안드로이드OS는 프로그램코드에 짜인 메서드의 이름을 알아야지 메서드 호출이 가능함
1. 안드로이드OS가 알고있는 이름으로 메서드를 호출하던가
2. 안드로이드OS가 알 수 있게 이름을 알려줘야 함(어떤 파일에 기록해서 OS가 읽을 수 있게)

코틀린을 동작시키는 VM에서 처음 실행하는 코드가 main()함수로 정해져있음
프로그래머는 main()함수를 만들어서 VM이 해당 함수를 실행할수있게 해주는 것임

보통 자바계열에서는 1번 방법으로 함

버튼을 만들 때
안드로이드OS가 버튼 클래스를 만들고 클릭 메서드를 정의해둠
안드로이드OS에서는 버튼 클릭을 감지할 수 있게 대기하다가 클릭이 감지되면 메서드를 호출할 수 있게 해줌
안드로이드앱을 만들면서 해당 클래스를 상속하고 클릭 메서드를 오버라이딩한 객체를 생성해주면 객체 주소값이 안드로이드 OS에 전달됨
안드로이드 OS는 전달받은 객체 주소값을 통해 실제 앱에 있는 메소드를 호출할 수 있음
앱사용자가 버튼을 클릭하면 안드로이드OS에서는 클릭 메서드를 호출

Any

  • Kotlin에서 사용하는 모든 클래스의 부모 클래스

  • 모든 클래스는 부모 클래스가 존재함(명시되지 않은 클래스의 경우 Any클래스)

  • 코틀린은 클래스를 작성할 때 상속받지 않는다면 자동으로 Any클래스를 상속받는다

  • 자바 Object -> 코틀린 Any

  • Any 클래스에는 모든 객체가 가지고 있어야할 메서드가 제공되고 있으며 이 메서드를 Overriding하여 각 클래스의 성격에 맞게 재구현하여 사용할 수 있다.

  • 코틀린에서 모든 클래스는 Any를 상속받기 때문에 모든 객체는 Any 타입 변수에 담을 수 있다.

fun main() {
    // 코틀린에서 모든 클래스는 Any를 상속받기 때문에 모든 객체는
    // Any 타입 변수에 담을 수 있다.
    val a1:Any = TestClass1()
    val a2:Any = TestClass2()
    println("a1 : $a1")
    println("a2 : $a2")
}

// 상속 관계를 설정하지 않았지만 Any를 상속받는다.
class TestClass1
class TestClass2
a1 : TestClass1@cbd64252
a2 : TestClass2@24e84fc1
  • toString 메서드 구현
class TestClass3{
    
    // toString 메서드 구현
    // toString : 객체를 문자열로 변환하는 의미의 메서드
    // 객체의 주소값을 가지고 있는 변수를 출력하면 toString 메서드가 호출되고
    // 여기서 반환하는 문자열을 출력해준다.
    override fun toString(): String {
        // return super.toString()
        return "TestClass3을 통해 만든 객체입니다"
    }
}

fun main(){
    val t3 = TestClass3()
    println("t3 : $t3 ")
}
t3 : TestClass3을 통해 만든 객체입니다 
  • 강사님의 경우 객체가 갖고 있는 property들의 값을 출력해보는 코드를 같이 구현한다고 한다.
class TestClass3(var a1:Int, var a2:Int){
 
    override fun toString(): String {
        // return super.toString()
        // 강사는 객체가 가지고 있는 property들의 값을 출력해보는 코드를 넣어놓습니다.
        println("a1 : $a1")
        println("a2 : $a2")
        return "TestClass3을 통해 만든 객체입니다"
    }
}

fun main(){
    val t3 = TestClass3(100,200)
    println("t3 : $t3 ")
}
a1 : 100
a2 : 200
t3 : TestClass3을 통해 만든 객체입니다 

this와 super

  • let, apply, run, with, also 와 함께 참고(추후 고차함수 편에서)

this

  • 객체 자기 자신을 지칭
  • 멤버 변수와 메서드 내부의 변수를 구분할 때 사용
  • 멤버 메서드와 메서드 내부의 메서드를 구분할 때 사용
  • 생성자에서 다른 생성자를 호출할 때 사용

변수에서 this 사용

  • property(멤버 변수)를 지칭하는 용도로 사용한다.
  • 프로퍼티의 이름과 매개변수의 이름이 같을 경우 매개변수를 사용한다.
fun main() {
    val t1 = TestClass1()
    t1.testMethod1(200)
}

class TestClass1{
    // 프로퍼티
    var value1 = 100

    // 매개변수
    fun testMethod1(value1:Int){
        println("value1 : $value1")
    }
}
value1 : 200
  • 프로퍼티의 이름과 매개변수의 이름이 같을 경우 매개변수가 아닌 프로퍼티를 사용하겠다면 this를 통해 객체에 접근해 사용하면 된다.
fun main() {
    val t1 = TestClass1()
    t1.testMethod1(200)
}

class TestClass1{
    // 프로퍼티
    var value1 = 100

    // 매개변수
    fun testMethod1(value1:Int){
        // 프로퍼티의 이름과 매개변수의 이름이 같을 경우
        // 매개변수를 사용한다.
        println("value1 : $value1")
        // 프로퍼티의 이름과 매개변수의 이름이 같은 경우
        // 매개변수가 아닌 프로퍼티를 사용하겠다면
        // this를 통해 객체에 접근해 사용하면 된다.
        println("this.value1 : ${this.value1}")
    }
}
value1 : 200
this.value1 : 100

생성자에서 this 사용

  • 다른 생성자를 호출하기 위해 사용한다.
fun main() {
    val t2 = TestClass2()
    println("t2 : $t2")
}

class TestClass2{

    // this() : 다른 생성자를 호출한다.
    // 만약 클래스에 주 생성자가 정의되어 있다면 무조건 주 생성자를 반드시 호출하도록 해야 한다.
    constructor() : this(100){
        println("매개 변수가 없는 생성자 호출")
    }

    constructor(a1:Int){
        println("매개 변수가 있는 생성자 호출")
        println("a1 : $a1")
    }
}
매개 변수가 있는 생성자 호출
a1 : 100
매개 변수가 없는 생성자 호출
t2 : TestClass2@3ab9d975

메서드에서 this 사용

  • 멤버 메서드와 지역 메서드를 구분하기 위해 사용한다.
  • 코틀린은 메서드(외부) 안에 메서드(내부)를 만들 수 있다.
  • 메서드(외부)내의 메서드(내부)는 메서드(외부)에서만 사용이 가능하다.
fun main() {
    val t1 = TestClass1()
    t1.testMethod2()
}

class TestClass1{
    ...
    // 코틀린은 메서드(외부) 안에 메서드(내부)를 만들 수 있다.
    // 메서드(외부)내의 메서드(내부)는 메서드(외부)에서만 사용이 가능하다.
    fun testMethod2(){

        fun innerMethod1(){
            println("innerMethod1 호출")
        }

        innerMethod1()
    }

}
innerMethod1 호출
  • 클래스의 멤버 메서드와 동일한 메서드를 내부에 만들어주는 경우
fun main() {
    val t1 = TestClass1()
    t1.testMethod2()
}

class TestClass1{
	...
    fun testMethod2(){

        fun innerMethod1(){
            println("innerMethod1 호출")
        }

        innerMethod1()

        // 클래스의 멤버 메서드와 동일한 메서드를 내부에 만들어준다.
        fun testMethod3(){
            println("testMethod2 메서드의 내부 메서드 testMethod3")
        }
        // 메서드 내부에 만든 메서드가 호출된다.
        testMethod3()
        // 만약 멤버 메서드를 호출하고 싶다면 this를 이용하여 호출한다.
        this.testMethod3()
    }
    
    fun testMethod3(){
        println("TestClass1의 testMethod3")
    }
    
}
testMethod2 메서드의 내부 메서드 testMethod3
TestClass1의 testMethod3

super

  • 부모 영역을 지칭
  • 멤버 변수와 상속받은 멤버 변수를 구분할 때 사용
  • overriding한 메서드와 부모의 메서드를 구분할 때 사용
  • 부모의 생성자를 호출할 때 사용

매개변수의 이름이나 프로퍼티의 이름이 부모의 프로퍼티 이름과 동일할 경우

  • super를 통해 부모의 프로퍼티에 접근한다.
fun main() {
    val sub1 = SubClass1()
    sub1.subMethod1(300)
}

open class SuperClass1{
    // 자식 클래스에서 동일한 이름의 프로퍼티를 만드는 것을 허용하겠다면 open 을 붙여줌
    open var superValue1 = 100
}

class SubClass1 : SuperClass1(){
    // 부모 클래스에 정의된 프로퍼티와 동일한 이름의 프로퍼티를 만들고자 한다면
    // 부모가 가지고 있는 프로퍼티 중에 open 프로퍼티만 가능하며
    // 앞에 override 키워드를 붙여줘야 한다.
    override var superValue1 = 200

    fun subMethod1(superValue1:Int){
        // 매개변수 사용
        println("superValue1 : $superValue1")
        // 매개변수의 이름과 프로퍼티의 이름이 같기 때문에 프로퍼티에 접근하려면
        // this 를 사용해야 한다.
        // 만약 동일명의 매개변수가 없다면 this 는 생략 가능
        println("this.superValue1 : ${this.superValue1}")
        // 매개변수의 이름이나 프로퍼티의 이름이 부모의 프로퍼티 이름과 동일할 경우
        // super를 통해 부모의 프로퍼티에 접근한다.
        println("super.superValue1 : ${super.superValue1}")
    }
}
superValue1 : 300
this.superValue1 : 200
super.superValue1 : 100

메서드의 이름이 부모의 메서드와 동일할 경우

  • super를 통해 부모의 메서드에 접근한다.
fun main() {
    val sub1 = SubClass1()
    sub1.subMethod2()
}


open class SuperClass1{
    ...
    
    // 자식 클래스에서 메서드를 재구현(overriding)을 허용하겠다면 open 을 붙여준다.
    open fun superMethod2(){
        println("SuperClass1의 superMethod2")
    }
}

class SubClass1 : SuperClass1(){
    ...

    // 부모 클래스의 메서드를 overriding 한다.
    override fun superMethod2() {
        println("SubClass1의 superMethod2")
    }
    
    fun subMethod2(){
        superMethod2()
        // 부모의 메서드를 자식에서 재구현한 경우 부모의 메서드를 호출하고자 한다면 super를 사용
        super.superMethod2()
    }
}
SubClass1의 superMethod2
SuperClass1의 superMethod2

생성자에서 접근

  • 코틀린의 모든 클래스는 생성자에서 부모 클래스의 생성자 호출을 명시하지 않으면 자동으로 부모의 생성자 중 매개변수가 없는 생성자가 호출된다.
    만약 호출되는 부모의 생성자를 명시적으로 지칭하겠다면 super를 사용한다.
fun main() {
    val sub1 = SubClass1()
}

open class SuperClass1{
    ...
    
    // 생성자
    constructor(){
        println("SuperClass1의 생성자")
    }

    constructor(a1:Int){
        println("매개 변수를 가지고 있는 SuperClass1의 생성자")
        println("a1 : $a1")
    }

    ...
}

class SubClass1 : SuperClass1{
    ...
    // 코틀린의 모든 클래스는 생성자에서 부모 클래스의 생성자 호출을 명시하지 않으면
    // 자동으로 부모의 생성자 중 매개변수가 없는 생성자가 호출된다.
    // 만약 호출되는 부모의 생성자를 명시적으로 지칭하겠다면 super를 사용한다.
    constructor() : super(1000){
        println("SubClass1의 생성자 호출")
    }
    ...
}
매개 변수를 가지고 있는 SuperClass1의 생성자
a1 : 1000
SubClass1의 생성자 호출

EX15 학생관리

EX13에서 운동부별로 입출력메서드 이름이 달랐는데
오버라이딩을 통해 메서드를 동일하게 통일시켜줌

EX16 동물원

EX14에서 동물별로 입출력메서드 이름이 달랐는데
오버라이딩을 통해 메서드를 동일하게 통일시켜줌

추상클래스

추상 메서드와 추상 클래스

  • 추상 메서드는 구현되지 않은 메서드를 의미
  • 추상 클래스는 추상 메서드를 가지고 있는 클래스를 의미
  • 추상 클래스는 구현되지 않은 추상 메서드를 가지고 있기 때문에 완벽한 설계도가 아님
    이때문에 추상클래스를 통해 객체를 생성할 수 없다.

추상 클래스의 상속

  • 클래스를 사용하는 방법은 2가지이며 하나는 객체를 생성하는 것이고 또 하나는 상속이다.
  • 객체를 생성하려면 추상 클래스를 상속받은 클래스를 만들고 추상 메서드를 구현하여 자식 클래스를 통해 객체를 생성해야 한다.
  • 추상 클래스의 목적은 자식 클래스에서 메서드를 Overriding하게 하기 위한 강제성을 부여하기 위함이다.
  • 추상클래스A를 클래스B가 상속받았는데 모든 메서드를 Overriding하지 않으면 클래스B도 추상클래스가 된다.
  • 안드로이드에서는 많은 클래스들이 추상클래스로 제공되며, 개발자가 추상클래스를 상속받아 메서드를 직접 오버라이딩 하도록 유도함
fun main() {
    // 추상 클래스의 객체 생성
    // 추상 클래스는 완벽한 클래스가 아니기 때문에 객체를 생성하는 것이 불가능하다.
    // val t1 = TestClass1() // 에러남

    // 추상 클래스를 상속 받은 클래스의 객체를 생성한다.
    val sub1 = SubClass1()
    sub1.testMethod1()
    sub1.testMethod2()
    sub1.testMethod3()
}


// 추상 클래스는 abstract 키워드를 붙혀줘야 한다.
// 추상 클래스는 상속이 가능해야 하기 때문에 open 키워드를 붙혀줘야 한다.
open abstract class TestClass1{

    fun testMethod1(){
        println("TestClass1의 testMethod1")
    }

    fun testMethod2(){
        println("TestClass1의 testMethod2")
    }

    // 추상 메서드
    // 추상 메서드는 추상 메서드임을 알리기 위해 abstract 라는 키워드를 붙여줘야 한다.
    // 추상 메서드는 overriding이 가능해야 하기 때문에 반드시 open을 붙혀줘야 한다.
    open abstract fun testMethod3()
}

// 추상클래스를 상속받은 클래스
class SubClass1 : TestClass1() {
    
    // 추상 메서드 구현
    override fun testMethod3() {
        println("SubClass1에서 구현한 testMethod3")
    }
}
TestClass1의 testMethod1
TestClass1의 testMethod2
SubClass1에서 구현한 testMethod3
  • 추상 클래스는 abstract 키워드를 붙혀줘야 한다.
  • 추상 클래스는 상속이 가능해야 하기 때문에 open 키워드를 붙혀줘야 한다.(구 버전)
  • 추상 메서드는 추상 메서드임을 알리기 위해 abstract 라는 키워드를 붙여줘야 한다.
  • 추상 메서드는 overriding이 가능해야 하기 때문에 반드시 open을 붙혀줘야 한다.(구 버전)
  • open 키워드는 코틀린 구버전에서만 강제되며 이후 버전에서는 생략이 가능하다.

인터페이스

  • 자바와 코틀린에서는 단일 상속만 지원하고 있음(하나의 클래스는 하나의 클래스만 상속 가능)
  • 인터페이스는 "개발자의 편의"를 위해 제공하는 개념이며, 간혹 다른곳에서 설명하는 "다중상속을 지원하기 위해 인터페이스를 제공한다" 라는 말은 틀린 말임
  • 자기 타입의 변수나 부모형 타입 변수에만 담을 수 있다.
  • 생성된 객체의 주소 값을 다양한 타입의 변수에 담을 수 있도록 한다면 인터페이스를 활용하면 된다.
  • 객체를 생성할 때 사용할 수 없음(인터페이스는 객체를 위한 설계도가 아님)
  • 클래스는 한 개 이상의 인터페이스를 "구현(implements)"할 수 있다.
  • 옛날 자바에는 인터페이스에 추상메서드만 존재했으나 이후에는 완전한 메서드도 같이 존재할 수 있게 됨

추상클래스 상속 방법

fun main() {
    val t1 = SubClass1()
    val t2 = SubClass2()

    testFunction1(t1)
    testFunction2(t2)
}

// 추상 클래스
abstract class AbstractClass1{
    abstract fun abstractMethod1()
}

abstract class AbstractClass2{
    abstract fun abstractMethod2()
}

// 객체의 주소값을 받아 메서드를 호출하는 함수
fun testFunction1(t100:AbstractClass1){
    t100.abstractMethod1()
}

fun testFunction2(t200:AbstractClass2){
    t200.abstractMethod2()
}


// 코틀린(자바 포함)에서는 단일 상속만 지원되기 때문에 여러 클래스를 상속 받을 수 없다.
// class SubClass1 : AbstractClass1(), AbstractClass2() // 에러
// 추상 클래스 하나당 하나의 자식클래스를 만들어줘야 한다.
class SubClass1 : AbstractClass1(){
    override fun abstractMethod1() {
        println("SubClass1의 abstractMethod1")
    }
}

class SubClass2 : AbstractClass2(){
    override fun abstractMethod2() {
        println("SubClass2의 abstractMethod2")
    }
}
SubClass1의 abstractMethod1
SubClass2의 abstractMethod2

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

인터페이스 구현 방법

fun main() {
    val t10 = TestClass10()
    testFunction3(t10)
    testFunction4(t10)
}
// 인터페이스
interface Inter1{
    fun interfaceMethod1()
}
interface Inter2{
    fun interfaceMethod2()
}

fun testFunction3(inter1:Inter1){
    inter1.interfaceMethod1()
}

fun testFunction4(inter2:Inter2){
    inter2.interfaceMethod2()
}

// 인터페이스를 구현한 클래스
class TestClass10 : Inter1, Inter2{
    override fun interfaceMethod1() {
        println("TestClass10의 interfaceMethod1")
    }
    override fun interfaceMethod2() {
        println("TestClass10의 interfaceMethod2")
    }
}
TestClass10의 interfaceMethod1
TestClass10의 interfaceMethod2

Companion

정적 멤버

  • 클래스를 정의할 때 프로퍼티나 메서드를 정적 멤버로 정의하면 객체를 생성하지 않고 사용할 수 있다.
  • Java에서는 static을 사용하는데 Kotlin은 companion 객체를 사용한다.

일반 멤버 프로퍼티의 경우

fun main() {
    // 일반 멤버 프로퍼티는 객체를 생성할 때 마다 계속 생성된다.
    val t1 = TestClass1(100)
    val t2 = TestClass1(200)
    println("t1.a1 : ${t1.a1}")
    println("t2.a1 : ${t2.a1}")

    t1.a1 = 1000
    println("t1.a1 : ${t1.a1}")
    println("t2.a1 : ${t2.a1}")
}

class TestClass1{
    // 일반 멤버 프로퍼티
    var a1:Int

    constructor(a1:Int){
        this.a1 = a1
    }
}
t1.a1 : 100
t2.a1 : 200

t1.a1 : 1000
t2.a1 : 200

정적 멤버 프로퍼티의 경우

  • 정적 멤버는 객체를 생성하지 않고 사용한다.
  • 정적 멤버는 객체를 통한 접근이 불가하다.
fun main() {
    // 정적 멤버는 객체를 생성하지 않고 사용한다.
    // 클래스명.멤버이름
    println("TestClass1.a2 : ${TestClass1.a2}")
    
    // 정적 멤버는 객체를 통한 접근이 불가하다.
    val t1 = TestClass1(100)
    val t2 = TestClass1(200)
    // println("t1.a2 : ${t1.a2}") //에러
    // println("t2.a2 : ${t2.a2}") //에러
}

class TestClass1{
    // 일반 멤버 프로퍼티
    var a1:Int

    // 정적 멤버 정의
    companion object{
        // 정적 멤버 프로퍼티
        var a2:Int = 100
    }

    constructor(a1:Int){
        this.a1 = a1
    }
}
TestClass1.a2 : 100

정적 멤버 메서드의 경우

fun main() {
	TestClass1.testMethod2()
}

class TestClass1{
    // 일반 멤버 프로퍼티
    var a1:Int

    // 정적 멤버 정의
    companion object{
        // 정적 멤버 프로퍼티
        var a2:Int = 100

        // 정적 멤버 메서드
        fun testMethod2(){
            // 정적 프로퍼티 사용
            println("testMethod2 - a2 : $a2")
        }
    }

    constructor(a1:Int){
        this.a1 = a1
    }
}
testMethod2 - a2 : 100
  • 정적 메서드에서는 일반 멤버 프로퍼티를 사용할 수 없음
    정적 멤버 입장에서는 객체가 생성되었지 않을 가능성, 객체가 여러개가 만들어져있어 어떤 객체의 멤버인지 확인할 수 없는 등의 여러가지 이유 때문에 일반 멤버 프로퍼티는 사용이 불가하다.
class TestClass1{
    // 일반 멤버 프로퍼티
    var a1:Int

    // 정적 멤버 정의
    companion object{
        // 정적 멤버 프로퍼티
        var a2:Int = 100

        // 정적 멤버 메서드
        fun testMethod2(){
            // 정적 프로퍼티 사용
            println("testMethod2 - a2 : $a2")
            // 정적 메서드에서 일반 멤버 프로퍼티를 사용할 경우.
            //println("testMethod2 - a1 : $a1") // 에러
            //println("testMethod2 - a1 : ${this.a1}") // 에러
            // 정적 멤버는 객체를 생성하지 않아도 사용할 수 있다.
            // 이제, 정적 멤버 입장에서는 객체가 생성되었지 않을 가능성, 객체가 여러개가 만들어져있어
            // 어떤 객체의 멤버인지 확인할 수 없는 등의 여러가지 이유 때문에 일반 멤버 프로퍼티는 사용이 불가하다.
        }
    }

    constructor(a1:Int){
        this.a1 = a1
    }
}
  • 반대로 일반 멤버에서는 정적 멤버를 사용할 수 있다.
    정적 멤버들은 프로그램이 시작할 때 이미 메모리에 올라가있다.
    그 후에 개발자가 만든 코드가 동작하기 때문에 객체 생성 시점보다 정적 멤버들이
    메모리에 올라가는 시점이 더 앞서 있다. 이에 사용이 가능하다
    같은 클래스에 있는 정적 멤버 접근시에는 클래스의 이름을 생략할 수 있다.
fun main(){
	t1.testMethod1()
}


class TestClass1{
	...

    // 일반 멤버 메서드
    fun testMethod1(){
        println("a1 : $a1")
        // 일반 멤버 메서드에서는 정적 멤버를 사용할 수 있다.
        println("a2 : $a2")
        testMethod2()
    }
}
a1 : 1000
a2 : 100
testMethod2 - a2 : 100

자바 파일에 정의된 static 멤버를 코틀린에서 사용

// JavaMain.java

public class JavaMain {
    // 정적 변수
    public static int javaValue1 = 100;
    // 정적 메서드
    public static void javaMethod1(){
        System.out.println("JavaMethod1");
    }

    // 자바 프로그램에서의 시작 메서드
    public static void main(String [] args){

    }
}
fun main(){
    // Java 파일에 정의된 static멤버 사용
    // Java 파일에 정의된 정적 멤버 사용은 자유롭게 가능
    println("JavaMain.javaValue1 : ${JavaMain.javaValue1}")
    JavaMain.javaMethod1()
}
JavaMain.javaValue1 : 100
JavaMethod1

코틀린 파일에 정의된 companion object 정적 멤버를 자바에서 사용

  • 코틀린 클래스의 프로퍼티는 자바로 변환될때 getter,setter메서드가 자동 생성되는 점 참고
// main.kt
class TestClass2{

    companion object {
        var kotlinValue1 = 1000

        fun kotlinMethod(){
            println("kotlinMethod1")
        }
    }
}
// JavaMain.java
public class JavaMain {
    // 자바 프로그램에서의 시작 메서드
    public static void main(String [] args){
        // 코틀린에서 정의한 companion object의 정적 멤버 사용
        int a1 = TestClass2.Companion.getKotlinValue1();
        System.out.println("a1 : "+a1);
        TestClass2.Companion.kotlinMethod();
    }
}
a1 : 1000
kotlinMethod1



※ 출처 : 멋쟁이사자 앱스쿨 2기, 소프트캠퍼스 
profile
안드로이드공부

0개의 댓글