Kotlin Getters/Setters properties 살펴보기
개인 광고 영역
kotlin Getters/Setterss에 대해서 정리합니다.
코틀린 문서 properties 부분에 정리되어 있는 Getters and Setters의 내용을 참고하시면 되겠습니다.
Getters/Setters
Getters/Setters을 java에서는 직접 구현해야 합니다.
annotations을 이용하여 get/set을 자동으로 생성할 수도 있지만 과거 Android에서는 성능 이슈로 클래스에 대한 get/set을 만들지 않는 것을 권장하였습니다.(현재는 큰 차이가 없습니다.)
그래서 아래와 같이 작성합니다.
class User {
public String name;
public String age;
}
위와 같이 public 변수를 선언해서 직접 접근하고, 이를 get/set을 처리합니다.
또는 아래와 같이 get/set을 직접 구현합니다.
class User {
private String name;
private String age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
이를 통해 캡슐화(encapsulation)를 구현하고, 값에 대한 validation을 처리할 수 있습니다.
코틀린에서도 이를 제공합니다. kotlin에서 사용할 때와 java에서 사용할 때는 kotlin 클래스의 접근 방법은 조금 다릅니다.
예를 들면 다음의 kotlin data class
를 생성하고,
data class User(var name: String, val age: String)
java에서는 get/set을 자동으로 만들어주기 때문에 다음과 같이 User
클래스를 생성하고, get/set
을 통해서 접근 가능합니다.
class Sample {
public void test() {
User user = new User("name", "age");
user.setName("name");
user.getName();
user.getAge();
}
}
코틀린에서는 get/set이 아닌 직접 접근 방법으로 접근합니다.
class Sample {
fun test() {
val user = User("name", "age")
user.name = "name" // 설정
user.name // 출력
user.age // 출력
}
}
Kotlin에서의 data class 장점
- equals()/hashCode() 생성
- toString() : “User(name=John, age=42)” 출력
- componentN() functions
아래와 같이
componentN
을 통해서 접근이 가능하며,
val name = person.component1()
val age = person.component2()
또는 다음과 같이 a/b 변수 선언으로 처리도 가능합니다.
for ((a, b) in collection) { ... }
- copy() function
Getters and Setters
var 타입의 원형은 아래와 같습니다.
propertyName: type = default 값으로 구성되고, getter/setter을 추가할 수 있습니다.
var <propertyName>: <PropertyType> [= <property_initializer>]
[<getter>]
[<setter>]
getter/setter을 각각 구성할 수 있는데 먼저 java에서는 다음과 같이 구성할 수 있습니다.
미리 validation을 통해 검증을 하고, 안전하게 처리할 수 있습니다.
class Test {
private String name;
public void setName(String name) {
if (TextUtils.ieEmpty(name) == false) {
this.name = name;
} else {
this.name = "";
}
}
public String getName() {
return TextUtils.isEmpty(name) == false ? name : "";
}
}
이를 코틀린에서는 아래와 같이 처리할 수 있습니다.
별도의 get/set 메소드를 생성하는 것이 아닌 선언과 동시에 값을 validation 하고, 이에 따른 결과를 처리할 수 있습니다.
class Test {
var name: String = ""
get() = if (field.length > 0) field else "name"
set (value) {
if (value.length > 0) field = value else ""
}
}
Backing Fields
위에서 적은 field는 Backing Fields라고 합니다. 바로 위와 같이 정리하였듯 validation을 처리해야 하는 경우가 발생합니다.
이때 위와 같이 Backing field를 이용하여 처리함으로 값에 대한 validation 후 값을 초기화하거나, return 할 수 있습니다.
class Test {
var count: Int = 0
set(value) {
if (value > 0) {
field = value
}
}
}
위의 코드는 count에 set 한 값이 0 보다 큰 경우를 체크합니다.
private 변수 만들기
예를 들면 변수를 설정할 때는 private으로 정의하고, 읽을 때는 public으로 정의해야 하는 경우가 있습니다.
이럴 경우에는 java에서는 아래와 같이 할 수 있습니다.
class Test {
private String name = "userName";
public String getName() {
return name;
}
}
위와 같이 클래스 내부에서만 초기화할 수 있고, 외부에서는 초기화할 수 없어야 하는 경우에는 java에서는 위와 같이 할 수 있습니다.
이를 kotlin으로 작업하면 다음과 같이 간단한 코드로 초기화 가능합니다.
class Test {
var name: String = "userName"
private set()
}
private set()
으로 간단하게 초기화가 가능하고, 이 변수는 내부에서는 접근이 불가능한 private setters를 가집니다.
Custom getters/setters
변수이지만 함수 자체로서의 getter/setter도 정의할 수 있습니다.
java에서는 별도의 함수를 정의해서 특정 값의 boolean을 체크하거나, size를 체크하거나 하지만
public class Test {
private int count = 0;
public boolean isEmpty() {
return count == 0;
}
}
kotlin에서는 간단하게 아래와 같이 특정 변수의 크기를 확인할 수 있습니다.
class Test {
var count = 0
var isEmpty: Boolean
get() = this.count == 0
}
get()을 통해서 Test
클래스의 count
를 체크하고, boolean을 리턴하게 됩니다.
또는 setters를 통해 다른 값을 초기화할 수도 있습니다.
class Test {
var name: String = ""
var userName: String
set (value) {
updateName(name)
}
fun updateName(name: String) {
// 생략
}
}
마무리
커스텀 getter/setters의 경우는 SAM conversions 또는 higher-order-functions을 구현해볼 수도 있습니다.
기존 글에서 다루었던 lateinit은 getter/setter와 함께 사용하지 못합니다. validation을 적용해야 한다면 lateinit 없이 사용하거나 Custom gatter/setter을 사용할 수 있습니다.
Comments