본문 바로가기

kotlin

constructor와 init

constructor와 init




kotlin의 생성자와 java의 생성자와는 좀 다르다.


우선 java의 생성자는 아래와 같이 필드에 있는 변수를 선언하고 생성자를 통해 주입한다.


public class C {

private String name;
private String age;
private String name2;

public C(String name , String age, String name2){
this.name = name;
this.age = age;
this.name2 = name2;
}

}


하지만 kotlin 에서는 아래의 한줄로 위의 java의 기능을 할 수 있다.


class A (var name : String, var age: String , var name2: String){


위의 Kotlin코드를 디컴파일 한 java 코드는 이렇다.


public final class A {
@NotNull
private String name;
@NotNull
private String age;
@NotNull
private String name2;

@NotNull
public final String getName() {
return this.name;
}

public final void setName(@NotNull String var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
this.name = var1;
}

@NotNull
public final String getAge() {
return this.age;
}

public final void setAge(@NotNull String var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
this.age = var1;
}

@NotNull
public final String getName2() {
return this.name2;
}

public final void setName2(@NotNull String var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
this.name2 = var1;
}

public A(@NotNull String name, @NotNull String age, @NotNull String name2) {
Intrinsics.checkParameterIsNotNull(name, "name");
Intrinsics.checkParameterIsNotNull(age, "age");
Intrinsics.checkParameterIsNotNull(name2, "name2");
super();
this.name = name;
this.age = age;
this.name2 = name2;
}
}


생성자와 프로퍼티 까지 전부 만들어 지는 모양새이다. 





kotlin의 constructor는 생성자 처럼 사용이 가능하지만 java의 생성자와는 다르기때문에 java와 혼용해서 사용하려면 적절한 배합이 필요함


아래 코드와 같이 kotlin에서 class 옆에 붙어 있는 생성자를 primary constructor 라고 한다.


class A (var name : String, var age: String , var name2: String){


아래와 같이 class 밑에 쓰여진 contstructor는 secondary constructor 라고 한다.  각 constructor 마다 this() 키워드로 class내의 다른 constructor의 


인자값에 넣고 호출 할 수 있다.


class A {

constructor(name: String = "aa") {
println("하나")
}

constructor(name: String, age: Int) : this(name){
println("둘")
}

constructor(name: String, age: Int, name2: String) : this(name , age){
println("셋")
}
}


그렇다면 init{ } 블록은 무었일까?


init 은 kotlin 문서에 따르면 다음과 같이 설명한다.



'기본 생성자에는 코드가 포함될 수 없습니다. 초기화 코드는 init 키워드가 접두어로 붙은 이니셜 라이저 블록에 위치 할 수 있습니다.'


즉 기본 constructor에서는 코드가 포함될 수 없으며 초기화 코드는 init block으로 시작해야 한다는 정의이다.


그리고 최상위 constructor에서만 var/ val  변수를 가질 수 있으며, 하위 constructor 에서 var/val 을 정의하면 오류가 발생한다.


그렇다면 init{ } 이 호출되는 시점은 언제인가



class A {

init {
println("이닛")
}

constructor(name: String = "aa") {
println("하나")
}

constructor(name: String, age: Int) : this(name){
println("둘")
}

constructor(name: String, age: Int, name2: String) : this(name , age){
println("셋")
}
}


아래와 같이 init 블럭과 다수의 constructor 블럭을 가지고 호출되는 시점을 파악해 보았다. 또한 this() 키워드로 내부의 다른 constructor를 호출한다.




다음과 같은 결과창이 나오는 것을 확인 할 수 있다.


호출되는 시점과 동작하여 출력하는 시점은 즉 아래와 같다.




constructor(name, age, birthday) // 호출

this(name, age) // 호출

this(name) // 호출

init {} // 출력

this(name) { // 동작 } // 출력

this(name, age) { // 동작 } // 출력

constructor(name, age, birthday) { // 동작 } // 출력





init블럭은 class내부의 constructor 들이 모두 호출되고 처음으로 출력되는 블럭이다.


constructor가 몇개있던지 상관없이 init [ ] 블럭이 먼저 호출되는 것을 볼 수 있다.




'kotlin' 카테고리의 다른 글

Any , 타입변환  (0) 2018.12.06
asList와 toList  (0) 2018.12.04
Kotlin의 유용한 함수 - let, apply, run, with  (0) 2018.12.04
var 와 val  (0) 2018.12.03
kotlin의 코드생성 목적과 언어 설계  (0) 2018.12.03