kotlin 에서 object 키워드 의 세 가지 사용 장면

10079 단어 kotlinobject키워드
머리말
object 는 Kotlin 의 중요 한 키워드 이자 자바 에 없습니다.object 는 주로 다음 과 같은 세 가지 사용 장면 이 있 습 니 다.
대상자 성명(Object Declaration)동반 대상자(Companion Object)
  • 대상 표현 식(개체 표현 식)
  • 다음은 그들 이 나타 내 는 의미,용법 과 주의 점 을 일일이 소개 하고 이 편 을 본 후에 object 키워드 의 용법 을 완전히 파악 할 수 있 도록 한다.
    1. 개체 선언(Object Declaration)
    문법 적 의미:클래스 의 성명 과 이 클래스 를 정의 하 는 단일 대상 을 결합 합 니 다(즉,object 를 통 해 단일 모드 를 실현 합 니 다)
    기본 예시
    
    object RepositoryManager{
     fun method(){
      println("I'm in object declaration")
     }
    }
    클래스 키 워드 를 object 키워드 로 바 꾸 어 클래스 를 설명 하 는 동시에 대상 도 설명 합 니 다.이렇게 많은 코드 를 만 들 기만 하면 이 종 류 는 이미 하나의 예 이다.
    쓰다
    a.Kotlin 에서:
    
    fun main(args: Array<String>) {
     RepositoryManager.method()
    }
    자바 에서 정적 방법(kotlin 에 정적 방법 이 없 음)을 호출 하 는 것 처럼 정 의 된 방법 을 호출 하지만 실제로는 Repository Manager 류 의 단일 대상 을 사용 하여 인 스 턴 스 방법 을 호출 합 니 다.이것 에 대해 아직 이해 하지 못 한다 면 자바 에서 사용 하 는 것 에 대한 설명 을 살 펴 볼 수 있다.
    b.자바 에서:
    
    public class JavaTest {
     public static void main(String[] args) {
      RepositoryManager.INSTANCE.method();
     }
    }
    다시 말 하면 object declaration 의 클래스 는 최종 적 으로 컴 파일 되 었 습 니 다.하나의 클래스 는 정적 구성원 을 가지 고 자신 에 대한 인용 을 가지 고 있 습 니 다.그리고 이 정적 구성원 의 이름 은 INSTANCE 입 니 다.물론 이 INSTANCE 는 하나의 예 이기 때문에 이렇게 사용 할 수 있 습 니 다.이 Repository Manager 를 자바 코드 로 설명 하면 다음 코드 가 있 습 니 다.
    
    class RepositoryManager{
     private RepositoryManager(){}
     public static final RepositoryManager INSTANCE = new RepositoryManager();
    
    }
    4) 주의 점:
    일반 클래스 의 성명 과 마찬가지 로 속성,방법,코드 블록 초기 화 및 다른 클래스 를 계승 하거나 인 터 페 이 스 를 실현 할 수 있 지만 구조 기(메 인 구조 기 및 2 차 구조 기 포함)를 포함 할 수 없습니다.
    그것 도 하나의 내부 에 정의 할 수 있다.
    
     class ObjectOuter {
      object Inner{
       fun method(){
        println("I'm in inner class")
       }
      }
     }
     fun main(args: Array<String>) {
      ObjectOuter.Inner.method()
     }
    2.동반 대상(Companion object)
    동반 대상 을 논술 하기 전에 먼저 우 리 는 명확 하 게 해 야 한다.Kotlin 에 static 키워드 가 없다 는 것 은 정적 방법 과 정적 구성원 이 없다 는 것 을 의미한다.그러면 kotlin 에서 이러한 개념 을 나타 내 려 면 패키지 급 함수(package-level function)와 우리 가 여기 서 언급 한 동반 대상 을 대신 합 니 다.그것들 사이 의 차이 에 대해 서 는 급 하지 않 으 니,우리 나중에 다시 이야기 합 시다.
    문법 형식:
    
    class A{
     companion object      (    ){
      //define method and field here
     }
    }
    기본 예제:
    
    class ObjectTest {
    
     companion object MyObjec{
    
      val a = 20
    
      fun method() {
       println("I'm in companion object")
      }
     }
    }
    사용:
    a.Kotlin 에서:
    
    fun main(args: Array<String>) {
     //   
     ObjectTest.MyObject.method()
     println(ObjectTest.MyObject.a)
    
     //   (    )
     ObjectTest.method()
     println(ObjectTest.a)
    }
    여기 서 주의 하 십시오.정의(정의 할 때 동반 대상 이름 이 생략 되면 컴 파일 러 는 기본 이름 인 Companion 을 제공 합 니 다)와 호출 할 때 동반 대상 이름 은 생략 할 수 있 습 니 다.또한 방식 2 에서 호출 형식 에 주의 하 십시오.클래스 이름.방법 명()의 형식 을 통 해 이 루어 집 니 다.우 리 는 Object Test 류 를 생 성 하 는 대상 이 없 을 때 내부 동반 대상 에서 정의 하 는 속성 과 방법 을 호출 했 습 니 다.자바 의 정적 방법 과 유사 한 개념 입 니까?
    현상 을 통 해 본질 을 보다
    javap 명령 을 통 해 생 성 된 바이트 코드 를 보 여 줍 니 다:
    빨간색 상자 에서 이 MyObject 구성원 변수의 종 류 는 사용

    MyObject 라 는 내부 클래스.이것 은 외부 클래스 의 인용 이 없 으 며 정적 내부 클래스 의 형식 으로 존재 한 다 는 것 을 주의 하 십시오.
    우리 가 앞에서 남 긴 문 제 를 기억 합 니 다.자바 의 static 개념 을 대체 할 수 있 습 니 다.그러면 동반 대상 에서 정의 하 는 방법 과 가방 등급 함 수 는 어떤 차이 가 있 습 니까?
    먼저 패키지 등급 함 수 를 포함 하 는 kt 파일 을 역 컴 파일 합 니 다(또는 클래스 라 고 합 니 다).
    이 를 통 해 알 수 있 듯 이 ObjectTest 2.kt 파일 은 실제 적 으로 ObjectTest2Kt 라 는 클래스 를 만 들 고 이 kt 파일 에서 정의 하 는 최상 위 함수(패키지 급 함수)는 이러한 정적 방법의 형태 로 존재 합 니 다.
    그러면 이 제 는 남 겨 진 질문 에 대답 할 수 있 습 니 다.사실은 평 급 류(우선)중의 정적 방법 과 정적 내부 류 중의 방법의 차이 입 니 다.정적 내부 류 중의 방법 은 외부 류 에서 정 의 된 static 방법 과 구성원 을 방문 할 수 있 기 때 문 입 니 다.private(개인 구조 기 포함)라 도.우리 가 자주 사용 하 는 정적 내부 클래스 를 바탕 으로 하 는 단일 사례 모델 은 바로 이 점 을 바탕 으로 하 는 것 이다).평 급 클래스 의 방법 은 현재 클래스 의 정적 인 private 구성원 에 접근 할 수 없다.만약 에 문자 가 이렇게 묘사 하 는 것 이 직관 적 이지 않다 고 생각한다 면 다음 그림 을 보 겠 습 니 다(Kotlin in action 에서 훔 친 것).
    @JvmStatic 주해:우 리 는 앞에서 정 의 된 method 방법 에 이 주 해 를 추가 하고 다시 build 프로젝트 를 한 다음 에 ObjectTest 와 ObjectTest$MyObject 라 는 두 가지 종 류 를 역 컴 파일 하여 어떤 변화 가 있 는 지 봅 니 다.
    이 정적 내부 클래스 의 경우@JvmStatic 주 해 를 추가 하거나 추가 하지 않 는 구 조 는 변화 가 없습니다.그러나 목표 클래스 에 있어 정적 인 방법 이 현저히 많아 졌 습 니 다.그러면 우 리 는@JvmStatic 주해 의 역할 을 이해 하기 어렵 지 않 습 니 다.동반 대상 클래스 에서 정의 하 는 인 스 턴 스 방법 과 속성 을 목표 클래스 에 추가 하고 정적 인 형식 으로 존재 합 니 다.
    반생 대상 에 대해 마지막 으로 한 가지 보충 을 한다.한 가지 유형의 반생 대상 은 한 가지 만 있 을 수 있다.곰 곰 이 생각해 봐 도 이해 하기 쉬 워 요.동반 대상 의 이름 은 생략 할 수 있어 요.만약 에 여러 짝 꿍 대상 에 대응 할 수 있다 면 우 리 는 여러 짝 꿍 대상 에서 똑 같은 함 수 를 정 의 했 습 니 다.호출 할 때 도대체 어떤 짝 꿍 대상 을 사용 하 는 방법 입 니까?이 문법 규정 을 이해 하기 어렵 지 않다.
    3.대상 표현 식(Object Expression)
    자바 의 익명 내부 클래스 회고:
    대상 표현 식 을 배우 기 전에 자바 의 익명 내부 클래스 를 살 펴 보 자.
    
    interface Contents {
     void absMethod();
    }
    public class Hello {
    
     public Contents contents() {
      return new Contents() {
       
       @Override
       public void absMethod() {
        System.out.println("method invoked...");
       }
      };
     }
    
     public static void main(String[] args) {
    
      Hello hello = new Hello();
      hello.contents().absMethod(); //  method invoked...
     }
    }
    ``` new Contents()
    
    
    이 contents()방법 은 익명 내부 클래스 의 대상 을 되 돌려 줍 니 다.이 익명 내부 클래스 는 Contents 인 터 페 이 스 를 실현 합 니 다.이 코드 들 은 매우 익숙 해서 더 이상 말 하지 않 겠 다.지금 두 가지 제한 적 인 문 제 를 제기 합 니 다.
    a.익명 내부 클래스 에 속성 과 방법 을 새로 추가 하면 외부 에서 호출 할 수 없습니다.
    
    return new Contents() {
    private int i = 1;
      public int value() {
       return i;
      }
    
      @Override
      public void absMethod() {
       System.out.println("method invoked...");
      }
     };
    
    public static void main(String[] args) {
     Hello hello = new Hello();
     hello.contents().absMethod();
     hello.contents().value(); //Cannot resolve method 'value()'
    }
    이 value 방법 을 사용 하고 싶 을 때 컴 파일 러 가 잘못 보고 할 수 있 습 니 다.이해 하기 쉽다.다 태 적 인 지식 이다.부모 유형의 인용 은 하위 클래스 추가 방법의 존 재 를 알 수 없다.
    b.익명 의 내부 클래스 는 하나의 인 터 페 이 스 를 실현 하거나 하나의 클래스 를 계승 하 는 것 이 고 하나 일 수 밖 에 없다.수학 용어 로'있 고 하나 밖 에 없다'고 말한다.
    2)문법 형식:
    object[:인터페이스 1,인터페이스 2,유형 1,유형 2]{}    //중 괄호 중 생략 가능
    3)사용 예시:
    a.인터페이스 또는 클래스 구현
    
    interface AA {
    fun a()
    }
    fun main(args: Array) {
    val aa = object : AA {
     override fun a() {
      println("a invoked")
     }
    }
    
    aa.a()
    }
    b.어떠한 인터페이스 와 클래스 도 실현 하지 않 고 익명 내부 클래스 에 방법 을 추가 합 니 다.
    
    fun main(args: Array) {
    val obj = object {
     fun a() {
      println("a invoked")
     }
    }
    
    obj.a() //  :a invoked
    
    }
    이 예 를 통 해 알 수 있 듯 이 앞에서 언급 한 자바 익명 내부 류 의 첫 번 째 한 계 는 Kotlin 에 존재 하지 않 고 새로 추가 하 는 방법 도 호출 할 수 있 습 니 다.
    c.여러 인터페이스 와 클래스 구현
    
    fun main(args: Array) {
    val cc = object : AA, BB() {
    override fun a() {
     }
    
     override fun b() {
    
     }
    
    }
    
    cc.a()
    cc.b()
    }
    이 예 를 통 해 알 수 있 듯 이 앞에서 언급 한 자바 익명 내부 류 의 두 번 째 한계점 은 kotlin 에 도 존재 하지 않 는 다.
    4)사용 주의 점:
    이것 은 Kotlin 공식 문서 의 한 단락 입 니 다.익명 의 대상 은 국부 변수 와 private 구성원 변수 로 정 의 될 때 만 실제 유형 을 나 타 낼 수 있 습 니 다.익명 의 대상 을 Public 함수 의 반환 값 이나 Public 속성 으로 볼 때 부모 클래스 로 만 볼 수 있 습 니 다.물론 어떤 유형 도 지정 하지 않 았 을 때 Any 로 생각 합 니 다.이 때 익명 의 대상 에 추 가 된 속성 과 방법 은 접근 할 수 없습니다.
    다시 예 를 들 어 여러분 의 이 해 를 돕 겠 습 니 다.
    
    class MyTest {
    private val foo = object {
     fun method() {
      println("private")
     }
    }
    
    val foo2 = object {
     fun method() {
      println("public")
     }
    }
    
    fun m() = object {
     fun method(){
      println("method")
     }
    }
    
    fun invoke(){
    
     val local = object {
      fun method(){
       println("local")
      }
     }
    
     local.method() //    
     foo.method() //    
     foo2.method() //     
     m().method() //     
    }
    }
    5)익명 의 대상 에서 같은 역할 로 정 의 된 부분 변 수 를 방문 하 는 문제:
    자바 에서 익명 내부 클래스 에서 외부 에서 정 의 된 부분 변 수 를 방문 하면 이 부분 변 수 는 final 키 워드 를 사용 하여 수식 해 야 합 니 다.왜 여러분 이 제 이전의 박문 을 볼 수 있 는 지 에 대해 서 는.Kotlin 에서 이 제한 이 없습니다.다음 의 예 를 보십시오.
    
    var a = 1
    val obj = object {
    fun method() {
    a++
    }
    }
    obj.method()
    println(a) //   2
    다시 한 번 설명 하 겠 습 니 다.자바 에서 실제 method 방법 에서 사용 하 는 a 는 실제 적 으로 부분 변수 a 의 복사 입 니 다.그 자체 가 아 닙 니 다.Kotlin 에 서 는 결국 JVM 이 실행 할 수 있 도록 바이트 코드 로 컴 파일 해 야 하기 때문에 본질 적 으로 이 점 에 어 긋 나 지 않 습 니 다.그럼 얘 는 어떻게 처리 하 는 거 예요?
    방문 한 부분 변수 가 val 일 때 자바 와 마찬가지 로 복사 본 을 가지 고 있 습 니 다.그리고 가 변 변수(var)일 때 그 값 은 Ref 와 같은 인 스 턴 스 구성원 에 저 장 됩 니 다.Ref 변 수 는 final 이 고 그 중의 구성원 변 수 는 바 꿀 수 있 습 니 다.역 컴 파일 후 Ref 의 모습 을 볼 수 있 습 니 다.
    여기에 재 미 있 는 코드 도 있어 서 여러분 께 붙 여 드 리 겠 습 니 다.
    
    fun tryToCountButtonClicks(button: Button): Int{
    var clicks = 0
    
    button.setOnClickListener{
     clicks++
    }
    
    return clicks
    }
    button 은 단추 입 니 다.이 코드 는 원래 Button 이 클릭 한 횟수 를 통계 하려 는 것 입 니 다.그러나 이 함수 의 반환 값 은 항상 0 입 니 다.아무리 여러 번 클릭 하 더 라 도.부분 변수 clicks 를 수정 할 가치 가 있 기 때문에 이 함수 의 반환 값 은 실행 할 때 확 정 된 것 입 니 다.바로 당신 의 값 이 아직 수정 되 지 않 았 고 함수 가 되 돌 아 왔 습 니 다.클릭 횟수 를 집계 하려 면 클릭 스 를 클래스 의 구성원 변수 로 정의 할 수 있 습 니 다.
    4.object declaration,Companion object 및 object expression 의 초기 화 시 기 를 비교 합 니 다.
    a.object declaration:처음 방문 할 때 초기 화 되 며 게 으 름 초기 화 입 니 다.
    b.Companion object:대응 하 는 클래스 가 불 러 온 후에 야 자바 의 정적 코드 블록 과 같이 초기 화 됩 니 다.
    c.object expression:실행 되면 바로 초기 화 합 니 다.
    이로써 Kotlin 의 object 키워드 사용 에 대해 소 개 를 마 쳤 습 니 다.많은 성 과 를 거두 시기 바 랍 니 다~
    총결산
    kotlin 에서 object 키 워드 를 사용 하 는 세 가지 장면 에 관 한 글 을 소개 합 니 다.더 많은 kotlin object 키 워드 는 장면 내용 을 사용 합 니 다.예전 의 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 부 탁 드 리 겠 습 니 다!

    좋은 웹페이지 즐겨찾기