엄범


``java extends / implements`` 구분 없이 그냥 ``kt :``붙이고 적는데, 클래스 상속인 경우 super class의 생성자를 호출해야 하므로 ``kt ()``를 붙여주어야 하고 인터페이스 구현인 경우 생성자가 없기 때문에 붙이지 않아야 하므로 이를 보면 둘을 구분할 수 있다.


주 생성자(primary constructor)

주 생성자는 클래스 이름 뒤에 오는 `` ()``로 둘러싸인 코드를 의미한다.

주 생성자의 파라미터는 1. 초기화 블록, 2. 프로퍼티 초기화 식, 3. 주 생성자 자체 에서만 접근할 수 있다.

1. 정석대로 초기화하면 이런 식이다.

생성자를 정의할 때는 ``kt contsructor`` 키워드를 사용한다. 
주 생성자의 body(초기화 블록) 지정은 ``kt init`` 키워드를 사용한다.

```kt

class User1 constructor(_name: String) {

    val name: String


    init {

        name = _name

        // this.name = _name    java나 python처럼 이렇게 해도 된다.

    }

}

```


2. 굳이 init을 사용할 필요가 없는 경우. 

Note ) 주 생성자 앞에 별다른 애노테이션이나 가시성 변경자가 없다면 ``kt constructor``를 생략할 수 있다.

```kt

class User2(_name: String) {

    val name = _name

}

```


3. 주 생성자에서 파라미터를 받으면서 동시에 프로퍼티 생성 및 초기화.

```kt

class User3(val name: String)

```


부 생성자(secondary constructor)

코틀린은 디폴트 파라미터를 지원하기 때문에 보통 주 생성자 만으로 해결이 되는데, 
파라미터 목록에 따라 다른 생성 방법을 지정해야 하는 경우 여러 개의 생성자를 정의해야 하는 상황도 있다.
  1. 디폴트 파라미터. 안되면
  2. 팩토리 메소드 패턴. 이것도 안되면
  3. 부 생성자를 고려한다.

주 생성자와 부 생성자를 함께 사용하는 경우

Note ) 주 생성자가 존재한다면 반드시 호출되어야 하므로, 부 생성자에서 호출해주어야 한다.
Note ) 부 생성자의 arg에는 ``kt val``을 적을 수 없다.
```kt
class User (val name: String){
    var nick = ""
    constructor(_name: String, _nick: String) : this(_name){  // 주 생성자 호출
        nick = _nick
    }
}
```

주 생성자를 사용하지 않고 부 생성자만 사용하는 경우

```kt
open class View {
//    constructor(ctx: Context) {
//    }
    constructor(ctx: Context, attr: AttributeSet) {
    }
}

class Button : View {
    constructor(ctx: Context)
        : this(ctx, MY_STYLE) {    // 자신의 다른 생성자에 객체 생성을 위임
    }
    constructor(ctx: Context, attr: AttributeSet)
        : super(ctx, attr) {       // View 생성자에 객체 생성을 위임
    }
}
```
Note ) 클래스에 주 생성자가 없다면 모든 부 생성자는 반드시 상위 클래스를 초기화하거나 다른 생성자에게 생성을 위임해야 한다.

인터페이스의 추상 프로퍼티

인터페이스에 프로퍼티를 선언할 수 있는데, 인터페이스가 상태를 가질 수는 없기 때문에 프로퍼티를 뒷받침하는 필드는 없다. 다만 그때그때 값을 계산해서 돌려줄 수 있는 게터와 세터를 지정할 수는 있다.(확장 프로퍼티와 유사하다.)
```kt
interface User {
    val email: String    // 반드시 override 해야 한다.
    val nick: String     // override하지 않고 사용할 수 있다.
        get() = email.substringBefore('@')
}
```