코틀린_InnerClass_Interface&익명클래스_companion object[=static]_늦은 초기화

소정·2023년 3월 22일
0

Kotlin

목록 보기
5/27

[1] 이너 클래스

  • 이너 클래스를 사용할 땐 이너는 바로 객체 생성 할 수 없음 (아웃터 없이 사용할 까봐)

  • 아웃터 클래스만이 이너 클래스를 객체로 만들수 있다

  • 코틀린에서 이너클래스가 되려면 inner 키워드를 써줘야함


fun main(){
  val obj = AAA()

  //val obj2 = BBB() // 이너는 밖에서 인식 안됨
  //이너 클래스는 외부에서 직접 객체생성 불가
  //아웃터 없이 사용 할깨봐 이너는 직접 만들 수 없음
  //이너 클래스 객체는 아웃터 클래스만 만들 수 있다
  val obj2:AAA.BBB = obj.getBBBinstance()
  obj2.show()
}

class AAA {
    var a: Int = 0

    fun show() {
        println("AAA 클래스 show : $a")
    }

    //이너클래스 객체를 생성하여 리턴해주는 기능 메소드
    fun getBBBinstance(): BBB {// 리턴 타입
        return BBB()
    }
	// 위 코드 간결화
    fun getBBBinstance() = BBB()

    //이너 크래스
    //코틀린에서 이너클래스가 되려면 inner 키워드를 써줘야함
    inner class BBB {

        fun show() { //상속 관계가 이니기 때문에 오버라이드 아님
            //이너 클래스의 장점
            //1. 아웃터의 멤버를 내것인양 사용
            a = 100
            println("아웃터 클래스의 멤버 a : $a")

            //아웃터의 show 메소드를 호출하기
            this@AAA.show()  // this@MainActivity 
            //이너에서 아웃터 부르는 행위
        }
    }
}

아웃터의 show 메소드를 호출하기
this@AAA.show() // cf) this@MainActivity
이너에서 아웃터 부르는 행위
메인 액티비티의 this부를 때 많이 사용함



[2] Interface

interface

  • interface란 추상메소드만 가진 class
  • abstract 생략 가능
  • 객체 생성 불가 ( 기능설계 없어서 )

interface를 구현할 별도의 클래스

  • 인터페이스의 추상메소드들을 구현하는 별도의 클래스를 설계하고 이 클래스를 객체로 만들어서 사용해야됨
  • implements 키워드 대신 상속처럼 : 기호 사용
  • 인터페이스를 구현할 때는 상속과 다르게 인터페이스명 옆에 () 생성자 호출은 없음

fun main() {

	//2. 인터페이스
    //객체 생성 불가 - 기능설계 안되어 있어서
    //var c:Clickable = Clickable() // error
    //인터페이스를 구현한 Test 클래스를 객체로 생성
    var c:Clickable = Test() //up casting (뭘 위해 만들었는지 강조하기 위해 업캐스팅 함)
    c.onclick()
    println()
}

//2. interface 추상메소드만 가진 class
interface Clickable {
    //abstract method - 이름만 있는 메소드
    //abstract fun onclick() - abstract 생략 가능
    fun onclick()

}

//인터페이스의 추상메소드들을 구현하는 별도의 클래스를 설계하고
//이 클래스를 객체로 만들어서 사용해야됨
// implements 키워드 대신 상속처럼 : 기호 사용
//인터페이스를 구현할 때는 상속과 다르게 인터페이스명 옆에 () 생성자 호출은 없음
class Test : Clickable {
    override fun onclick() {
        println("click!!!")
    }
}



[2-1] 익명클래스

  • 객체 생성 동시에 인터페이스를 그자리에서 구현하는 익명클래스 사용

🔨 object

익명 클래스 객체를 만드는 키워드

기존 자바에서 익명 클래스 구현 방법
var c2:Clickable = new Clickable {};


fun main() {
	//2-1. 익명 클래스
    //다른 기능을 하는 또 다른 Clickable이 필요
    //또 다시 Test 같은 새로운 class 를 명명하는 것이 싫음
    //객체 생성 동시에 인터페이스를 그자리에서 구현하는 익명클래스 사용
    //var c2:Clickable = new Clickable {}; //기존 자바에서 익명 클래스 구현 방법

    //코틀린에서 익명 클래스 만드는 방법
    // 익명 클래스 객체를 만드는 키워드 : object
    var c2:Clickable = object : Clickable{
        override fun onclick() {
            println("눌러 눌러")
        }
    }

}


//2. interface 추상메소드만 가진 class
interface Clickable {
    //abstract method - 이름만 있는 메소드
    //abstract fun onclick() - abstract 생략 가능
    fun onclick()

}

//인터페이스의 추상메소드들을 구현하는 별도의 클래스를 설계하고
//이 클래스를 객체로 만들어서 사용해야됨
// implements 키워드 대신 상속처럼 : 기호 사용
//인터페이스를 구현할 때는 상속과 다르게 인터페이스명 옆에 () 생성자 호출은 없음
class Test : Clickable {
    override fun onclick() {
        println("click!!!")
    }
}



[3] companion object[동반 객체] : static키워드 대체

  • 코틀린에는 static 키워드 없음
  • 정적 멤버 static 키워드의 대체 문법
  • 클래스(설계도면)에 붙어 있는 객체 같은 녀석
  • 별도의 객체 생성 없이 클래스명 만으로 접근 가능한 것

💡 어차피 전역변수가 있어서 만들지 않은 거 같지만 companion을 만든 이유는 소속감을 주기 위해 만든 거 같음

🔨 companion object {}

{} 안에 있는 멤버들은 이미 객체화 되어 있기 때문에 따로 객체 생성 없이 그냥 사용 가능, {} 안의 멤버들은 클래스명. 으로 접근!


fun main() {
	println(Sample.title) //클래스명.멤버변수
    println(Sample.show())
}


//4. 동반 객체 (자바 static 대체)
class Sample {
    var a:Int = 10 //인스턴스 변수는 객체 생성 할 때만 쓸수 있음

    //static var b:Int = 200 // -error : static 없음

    companion object {
        //이 안에 있는 멤버들은 이미 객체화 되어 있기 때문에 그냥 사용 가능
        //단, Sample 클래스에 동반되어 있기 떄문에 클래스명이 요구됨

        var title:String = "Hello"

        fun show(){
            println("동반 객체의 show()")
        }
    }
}



[4] 늦은 초기화

참조변수 만들때 코틀린은 반드시 초기화가 필요함
하지만 뷰는 onCreate() 될때 만들어지기때문에 늦은 초기화가 필요

4-1) lateinit

🧨 var 변수에만 사용

사용 특징
1) nullable 변수는 lateinit불가
lateinit var title:String? //에러
2) 기본 자료형(8개) 사용불가
lateinit var age:Int //에러 - 참조가 아니가 값이니 초기값 넣어라
3) val에는 사용 불가


fun main() {
	//4-1) lateinit [var 변수에만 사용]
    var h:Hello = Hello()
    //println(h.name) //Exception 발생
    h.onCreate() //초기화를 해줘야 
    println(h.name) // 객체 참조 가능
}

//4. 늦은 초기화
class Hello{

    //4-1) lateinit
    //var name:String - error 초기화 반드시 해야됨

    //초기화를 나중에 하고 싶다면...
    lateinit var name:String

    fun onCreate(){
        name = "sam" //이때 초기화
    }
    
    //lateinit 사용 특징
    //1) nullable 변수는 lateinit불가
    //lateinit var title:String? //에러

    //2)기본 자료형(8개) 사용불가
    //lateinit var age:Int //에러 - 참조가 아니가 값이니 초기값 넣어라
    
    //3) val에는 사용 불가

}

4-2) by lazy

by lazy 는 대입과 같은 것

🧨 val 변수에서만 사용

☝ 사용특징
1) 기본형 자료형도 가능
2) nullable도 가능
3) 조건값으로 값 대입도 가능함 ( { } 영역이 있으니까 )


fun main() {
	//4-2) by lazy [val 변수에서만 사용]
    println(h.addr) //add는 객체 생성 할 때 초기화
    println(h.address) //지금 이 순간 초기화 됨
    println(h.tel)
}


//4. 늦은 초기화
class Hello{

    //4-2) by lazy [val 변수에서만 사용]
    //val address:String //에러
    val address:String by lazy { //이 변수가 처음 사용 될 때 초기화 됨
        "seoul"
    }
    val addr:String = "busan" //이 순간 초기화 됨
    
    val tel:String by lazy { 
        println("늦은 초기화")
        "010-2222-1111"
    }

    //by lazy 특징
    //1) 기본형 자료형도 가능
    val age:Int by lazy { 20 }

    //2) nullable도 가능
    val message:String? by lazy { "Hello" }
    val message2:String? by lazy { null }
    
    //3) 조건값으로 값 대입도 가능함
    val message3:String? by lazy { 
        if (age < 20) "미성년자"
        else "성인"
    }

    //4) var 에는 사용 불가능
    //var sss:String by lazy { "aaa" } // error
}
profile
보조기억장치

0개의 댓글