본문 바로가기
코틀린 문법

4. 익명객체와 옵저버 패턴-코틀린 7일차

by 농농씨 2023. 4. 11.

코드테스트 사이트:play.kotlinlang.org

참조:유튜브 디모의 코틀린

 

 

//observer(옵저버):이벤트가 일어나는 것을 감시하는 감시자 
//이벤트: ex.안드로이드에서, 키의 입력, 터치의 발생, 데이터의 수신 등
//  함수로 직접 요청하지 않았지만 시스템 또는 루틴에 의해서 발생하게 되는
//  동작들
//옵저버 패턴:이벤트가 발생할 때마다 '즉각적으로 처리'할 수 있도록 만드는
//  프로그래밍 패턴
//이벤트 수신하는 클래스와 이벤트 발생 및 전달하는 클래스,총 두개 클래스 필요
//후자 클래스는 전자 클래스를 참조할 수 없어서 둘을 매개하는
//  '인터페이스'를 사용함
//후자에서는 자신의 이벤트를 받을 수 있는 인터페이스를 만들어 공개하고,
//  전자는 이를 구현하여 후자에 넘겨줌. 이 인터페이스를 observer라 함
//  또는 listener (in kotlin)
//callback:이벤트를 넘겨주는 행위
//옵저버 패턴을 구현해봅시다~

//이벤트를 수신해서 출력하는 eventprinter클래스와 
//숫자를 카운트하여 5의 배수마다 이벤트를 발생시킬 counter클래스
//그리고 이 둘을 연결할 인터페이스인 EventListener 인터페이스
fun main() {
    EventPrinter().start()//메인함수에서는 EventPrinter의 인스턴스를
     //생성하고 부탁할 start 함수만 호출해주면 됨
}

interface EventListener {//인터페이스로서 이벤트 발생할때 
     //숫자 반환할 예정
    fun onEvent(count: Int)//추상함수(?)만들고 패러미터로 정수 넘겨줌
}

class Counter(var listener: EventListener){
//이벤트 발생 클래스, 이벤트 발생 위해 인터페이스eventlistener를
//   속성으로 받음
fun count(){
        for(i in 1..100){//1~100 반복하면서
            if(i % 5==0) listener.onEvent(i)
            //5의 배수 될때마다 인터페이스의 onevent함수 호출함
        }
    }
}

class EventPrinterEventListener{//이름대문자잊지말기
    //이벤트를 받아서 화면에 호출할 클래스
    //EventListener 인터페이스를 상속하여 구현해야 함
    override fun onEvent(count: Int) {//인터페이스의 
        //on event 함수를 오버라이딩해서
        print("${count}-")//받아온 숫자와 대시문자 출력
    }
    fun start() {//새로운 함수 추가해주고
        val counter = Counter(this)//이벤트 발생 클래스인
         //Counter 클래스의 인스턴스를 만들어주고
         //this라는 키워드로 Eventlistener()의 구현부 넘겨줌(?그냥 넘겨줬단 뜻인듯?)
        counter.count()//그리고 count를 시작하게 해보죠(???)
    }
//여기서 this는 EventPrinter객체 자신을 나타내지만
//받는 쪽에서 EventListener만 요구했기 때문에 
//EventListener구현부만 넘겨주게 됨!

//(아하~ EventPrinter 클래스의 내부에서 this라는 키워드를 써서

//사실상 EventPrinter를 넘겨줘야하는데 EventPrinter가 EventListener를 상속받았으므로

//EventListener만 요구될 때에도 걔를 넘겨줄 수가 있다~)
//이를 '객체지향의 다형성'이라고 함(음...글쿤...)
//상속받아 만들어진 클래스는 수퍼클래스의 기능을 포함하여 제작되었으므로
//수퍼클래스에서 정의한 부분만 따로 넘겨줄 수 있다.
    
}

실행결과

 
//실행해보면 Counter가 5의 배수마다 이벤트를 발생시킨 것을
//EventPrinter 내에서 구현된 EventListener에서 '출력'하고 있음을
//알수있음(마지막 대시 없애는 방법도 고민해봅시다)

//그런데 EventPrinter가 EventListener를 상속받아 구현하지 않고 
//'임시로 만든' 별도의 EventListener객체를 대신 넘겨줄 수도 있음!!
//이것을 '이름이 없는 객체'라 하여 '익명 객체'라고 함



//"익명객체"
//EventPrinter클래스 지우고 다시시작~


fun main() {
    
    EventPrinter().start()
    
}

interface EventListener {
    fun onEvent(count: Int)
}

class Counter(var listener: EventListener){

fun count(){
        for(i in 1..100){
            if(i % 5==0) listener.onEvent(i)
        }
    }
}

class EventPrinter {//이번엔 EventListener를 상속받지 않고 
    fun start() {//바로 start함수 만들어보자
        val counter = Counter(object:EventListener{
         override fun onEvent(count:Int){    //onEvent를 override함
                print("${count}-")
            }
        })//(하나의 파라미터임)

        //그리고 카운터 인스턴스 만들 때
        //패러미터에 익명 객체 만들어서 넘김
        //'오브젝트'라는 키워드 여기서 사용!
        //object라 쓰고 이름없이 바로 콜론 쓰고 EventListener를
        //상속받게 하고

    //object부터 여기까지 긴 문장이 익명함수로 넘길 단 한개의 파라미터임 놀랍게도...
     counter.count() //항상 함수에는 ()붙어야한다는 점!!!
    }//지난 시간의 object와 형태는 비슷하나 차이는 '이름이 없다는 점'

     // 이렇게 만들면 인터페이스를 구현한 객체를 코드 중간에도 '즉시' 생성하여
    //사용할 수 있다
    
}
   

실행결과는 동일


//observer 패턴은 이벤트를 기반으로 동작하는 모든 코드에서 광범위하게 쓰이는 
//방식이므로 그 구조를 이해하는 것이 중요하다

 

코드실행 안되는데 좀 이해하고 다시 보려고 일단 저장;;;ㅎㅎ^^

드디어 이해했다...(23.05.04.)