1. 클래스와 프로퍼티
1) 코틀린에서는 getter,setter를 자동으로 생성
// 멤버변수만 생성해도, 알아서 getter,setter 사용 가능
public class Person(name:String, age:Int){
val name:String = name
var age:Int = age
}
2) 생성자에서 프로퍼티 생성 가능
public class Person(val name:String, var age:Int){
}
3) 클래스명.변수로 호출 가능
* 자바로 만들어진 클래스도 변수명으로 호출
* get, set함수가 아닌 변수명으로 직접 호출
fun main(){
val person = Pseron("test", 50)
println(person.name)
println(person.age)
pserson.age = 27
}
2. 생성자와 init
1) 코틀린에서는 init함수를 통해 초기 조건이나, 값 할당 가능
public class Person(val name:String, var age:Int){
init{
if(age <= 0){
throw IllegalArgumentException("맞지 않는 나이")
}
}
}
2) constructor키워드를 통해 추가 생성자를 만들 수 있음
public class Person(val name:String, var age:Int){
init{
if(age <= 0){
throw IllegalArgumentException("맞지 않는 나이")
}
}
// 새로운 생성자 생성
// this는 결국 맨 위의 생성자를 가리킴
constructor(name:String):this(name, 1)
}
* 주생성자(primary constructor)
- public class Person(val name:String, var age:Int){...}
와 같은 최초에 생성되는 생성자를 의미
- 반드시 존재해야하며, 파라미터가 하나도 없을 경우 생략 가능
* 부생성자(secondary constructor)
- constructor(name:String):this(name, 1) 와 같이 부가적인 생성자를 의미
- 추가적으로 생성자를 만들고 때 생성되는 생성자이므로 없어도 무방함
- 최종적으로 주생성자를 this 형태로 호출해야함.
- 부생성자는 body를 가질 수 있다
* 예시
public class Person(val name:String, var age:Int){
// 부생성자가 여러개 있어도 최종적으로 주생성자를 호출
constructor(name:String):this(name, 1){
println("첫 번째 부생성자")
}
constructor():this("test"){
println("두 번째 부생성자")
}
}
* 코틀린에서는 부생성자보단 디폴트 파라미터를 권장함
* Converting과 같은 경우 부생성자를 사용할 수 있으나, 정적 팩토리 메소드를 추천
3. 커스텀 getter, setter
1) 커스텀을 통해, 프로퍼티가 있는 것처럼 처리할 수 있음
public class Person(val name:String, var age:Int){
init{
if(age <= 0){
throw IllegalArgumentException("맞지 않는 나이")
}
}
constructor(name:String):this(name, 1)
// 위 아래는 같은 표현
val isAduld:Boolean
get() = this.age >= 20
val isAduld:Boolean
get() {
return this.age >= 20
}
}
2) 커스텀 getter 실전 예제
* Name을 첫 글자를 무조건 대문자로 만들때
public class Person(name:String, var age:Int){
val name = name
get() = field.uppercase()
init{
if(age <= 0){
throw IllegalArgumentException("맞지 않는 나이")
}
}
constructor(name:String):this(name, 1)
// 위 아래는 같은 표현
val isAduld:Boolean
get() = this.age >= 20
val isAduld:Boolean
get() {
return this.age >= 20
}
}
4. backing field
1) field키워드
호출되는 곳에서 name을 호출하게되면, 내부에서 get을 호출
get내부는 또 멤버변수 name을 호출하게되고, 다시 또 get을 호출
-> 즉 무한루프 발생
이런 현상을 막기위해 자기 자신(멤버의 name)을 가리키는
field키워드를 사용
2) 예시
* backing field키워드를 사용하지 않고도 구현 가능
public class Person(name:String, var age:Int){
var name = name
get() = field.uppercase()
// value는 대입되는 값, field는 자기자신
set(value){
field = value.uppercase()
}
val uppercaseName =
get() = this.name.uppercase()
fun getUppercaseName() = this.name.uppercase()
init{
if(age <= 0){
throw IllegalArgumentException("맞지 않는 나이")
}
}
constructor(name:String):this(name, 1)
// 위 아래는 같은 표현
val isAduld:Boolean
get() = this.age >= 20
val isAduld:Boolean
get() {
return this.age >= 20
}
}
* setter를 지양하고있고, update함수를 통해 값 변경을 주로 진행하기 때문에, custom setter는 잘 사용하지 않음