코틀린 언어 정리 2-1

class

주생성자 ( primary constructor )

주생성자 특징

  • 주생성자는 선언만 있습니다. 즉 일반 함수와 같은 구현 영역이 없습니다.
  • 주생성자는 매개변수를 클래스 내부로 전달해 줍니다. 여기서 클래스 내부는 프로퍼티 선언, init block 을 말합니다. ( 보조생성자를 포함한 다른 멤버 함수들의 구현 영역은 포함되지 않습니다. )

 

주생성자 선언 방법

class MyClass public constructor ( name:String, age:Int ) { ... }

⇒ constructor 및 접근 권한(public)을 직접 명시한 선언 방법입니다.

 

class MyClass constructor ( name:String, age:Int ) { ... }

⇒ constructor의 기본 접근 권한은 public이며 public을 다른 접근 권한으로 변경할 필요가 없다면 생략 가능합니다. 즉 접근 권한을 명시하지 않을 경우 public으로 기본 설정됩니다.

 

class MyClass ( name:String, age:Int ) { ... }

⇒ 접근 권한 등을 설정할 필요가 없는 경우 constructor 키워드도 생략할 수 있습니다.

 

class MyClass {}

⇒ 사용자가 주생성자를 선언하지 않은 형태입니다. 이런 경우 인자가 없는 주생성자가 자동으로 생성됩니다.

 

주생성자 구현

주생성자의 매개변수와 프로퍼티 동시 선언

주생성자

주생성자의 매개변수 선언 시 변수 이름 앞에 val/var을 추가하면 매개변수와 프로퍼티가 동시에 선언됩니다. 이 방식으로 프로퍼티를 선언한 경우 lateinit, lazy, get/set 등을 별도로 지정할 수 없습니다.

 

예제

class MyClass ( val name: String, var age: Int ) { }



보조생성자

보조생성자에서는 매개변수와 프로퍼티를 동시에 선언할 수 없습니다.

 

프로퍼티 선언 및 초기화

프로퍼티 선언 및 초기화 하는 부분에서 주생성자의 매개변수를 바로 사용할 수 있습니다. 즉 클래스 내부의 프로퍼티 선언 및 초기화 영역, init block 영역이 모두 주생성자의 구현부처럼 취급됩니다. 만약 주생성자의 매개변수 이름과 클래스 몸체에 선언한 프로퍼티의 이름이 겹치는 경우 주생성자의 매개변수가 우선합니다.(이런 경우 일반적으로 지역 이름이 전역 이름보다 우선합니다.)  이름이 겹치는 경우 프로퍼티를 참조하려면 this 키워드를 이용하면 됩니다.( ex. this.propertyName )

 

init block

위에서 언급한대로 클래스로 객체 생성 시 주생성자의 구현처럼 사용할 수 있습니다. 하지만 객체 생성 시 주생성자가 존재하지 않을 경우에도 init block은 실행됩니다.

 

예제

class TestNum(var value1: Int) {
   var value2: Int

   init {
       if (value1 > 10)
           value2 = 10
       else
           value2 = value1
   }
}

fun test() {
   var obj = TestNum(5)
   println(obj.value2)
}

위의 예제에서 init 키워드 이후 {}로 묶인 부분이 init block 영역입니다.



주생성자 자동선언

가능한 경우

주생성자 및 보조생성자를 선언하지 않은 경우 인자가 없는 주생성자가 자동으로 선언됩니다.

 

예제

class MyClass {}

 

불가능한 경우

사용자가 주생성자를 선언하지 않은 경우라도 보조생성자가 1개 이상 선언되어 있을 경우 주생성자가 자동으로 선언되지 않습니다.

 

예제

class MyClass { constructor () {} }

 

주의

주생성자 유무와 상관 없이 init block은 클래스로 객체 생성 시 생성자보다 먼저 실행됩니다.

 

예제

class TestNum {
   var value: Int

   init {
       println("TestNum::init run")
   }

   constructor (value: Int) {
       this.value = value
       println("TestNum::constructor ( value: Int )")
   }

   constructor (value: Int, additional: Int) {
       this.value = value
       println("TestNum::constructor ( value: Int, additional: Int )")
   }
}

fun test() {
   var obj = TestNum() // 컴파일 에러...보조생성자가 선언된 경우 주생성자가 자동으로 선언되지 않는다.
}

 

제약

주생성자는 클래스마다 1개 이하로 선언할 수 있습니다.



보조생성자 ( secondary constructors )

선언 방법

overloading( 매개변수 선언 형태로 구분되는 방법 )을 이용하여 원하는 만큼의 보조생성자를 선언할 수 있습니다.

 

예제

class Person {
   constructor (firstName: String) {}
   constructor (firstName: String, name: String) {}
   constructor (firstName: String, name: String, age: Int) {}
   // ...
}

 

제약

주생성자가 존재할 경우 보조생성자에서는 this 키워드를 이용해 주생성자를 반드시 호출하도록 구현해야 합니다.

 

예제

class MyClass(name: String) {
   val name: String
   var age: Int

   init {
       this.name = name
       age = 10
   }

   constructor (name: String, age: Int) : this(name) {
       this.age = age
   }
}

fun main(args: Array<String>) {
   var obj = MyClass("hong") // 주생성자 호출
   println("${obj.name}: ${obj.age}")
   obj = MyClass("kim", 30) // 보조생성자 + 주생성자 호출
   println("${obj.name}: ${obj.age}")
}

 

+ Recent posts