class Dog(val name: String, val weight: Double,
val isDog: Boolean = true) {
fun bark() {
println(if (weight < 20) "Yip!" else "Woof!")
}
}
Class 바로 옆에 괄호를 이용해서 사용될 value를 받아올 수 있다. 이러한 방식을 주 생성자
라고 부른다.
주 생성자는 class Dog(val name: String)
처럼 파라미터를 받음과 동시에 변수 선언을 동시에 처리할 수 있다. 주 생성자 파라미터에서 변수를 선언한 경우, 해당 property 가 클래스 내부에 선언된 것이기 때문에 동일한 이름의 property 가 class body 에 중복되어 존재해서는 안된다.
주 생성자는 val isDog: Boolean = true
처럼 선언한 변수를 초기화할 수 있다.
주 생성자는 파라미터만 받을 수도 있다. breed_param: String 은 변수 선언이 되지 않았기 때문에 파라미터만 받아온 것이다. 이를 class body에 정의된 property 구성을 위해 사용할 수 있다.
class Dog (var name: String, var weight: Int, breed_param: String) {
val breed = breed_param.uppercase()
}
주생성자를 통해 변수 선언과 파라미터 받기가 모두 가능한 것을 확인하였다. 만약 들어온 인자의 validation 을 하고 싶은 경우 어떻게 해야할까? .uppercase() 처럼 간단한 처리가 아닌 몇줄의 코드가 필요한 경우라면 init {...}
를 이용할 수 있다.
class Dog (val name : String, val weight: Double, val breed : String) {
var owner = "not me"
init {
if (name.equals("sam") &&
breed.equals("Golden Retriever") &&
(weight >= 6.0 && weight <= 8.0) ) {
owner = "me"
}
println("${name}s owner is ${owner}")
}
}
만약 Class Body 안에 여러 init{...} 을 사용할 경우 위에서 아래 순서대로 실행된다.
부 생성자
는 주 생성자를 직,간접적으로 호출해야한다. 부 생성자 내부의 this 키워드를 통해서 주 생섲아를 호출하게 된다.
class Dog (var name: String, var weight: Int) {
var owner: String = "James"
constructor(inputName: String, inputWeight: Int,
inputYou: String) : this(inputName, inputWeight){
this.owner = inputYou
}
init {
println("name : $name\nweight : $weight")
}
}
init{...} 은 주 생성자의 일부이기 때문에 부 생성자가 주 생성자를 호출할때 같이 실행된다. 그리고 그 순서상 부 생성자의 body 부분이 실행되기 전에 init{...} 이 순서대로 실행된다.
명시적인 주 생성자가 없다고 하더라고 부 생성자는 암묵적으로 주 생성자를 호출하고 역시나 init{...} 이 실행된다.
lateinit
원칙적으로 모든 변수(var, val, property) 는 초기화되어야 한다. 하지만 변수를 선언하는 순간(class 의 경우에는 인스턴스화하는 순간)에 변수의 값을 초기화 하지 못하겠다면 lateinit var 를 통해서 선언하는 순간은 아니지만, 나중에 해당 변수가 사용되기 전에 반드시 값을 할당할 것임을 컴파일러에게 알려줄 수 있다. 하지만 lateinit 은 Byte, Short, Int, Long, Double, Float, Char, Boolean 자료형에는 사용할 수 있다.
만약 주 생성자, 부 생성자 모두 없는 경우 어떤 argument도 없는 주 생성자가 생성된다.