var은 mutable, val 은 read-only
class Address{
var name:String = "Kotlin"
var city:String = "Seoul"
}
프로퍼티 사용은 자바의 필드를 사용하듯이 하면 된다.
fun copyAddress(address:Address) : Address{
val result = Address()
result.name=address.name
...
return result
}
그렇다는데 솔직히 아직 난 자바랑 무슨차인지 모르겠다.
프로퍼티란 자바필드의 변수적인 부분과, getter,settet의 함수적인 부분이 포함된 것이다. 뭔소리?????
예시를 보면서 이해를 해봅시다.
다음과 같은 코틀린 코드를
fun main(args:Array<String>){
var obj=Address()
println(obj.name)
}
class Address{
val name:String = "Kotlin" //프로퍼티
}
자바코드로 바꾼다면 다음과 같다.
public final class Other2Kt {
public static final void main(@NotNull String[] args) {
Intrinsics.checkNotNullParameter(args, "args");
Address obj = new Address();
String var2 = obj.getName();
System.out.println(var2);
}
}
public final class Address {
@NotNull
private final String name = "Kotlin";
@NotNull
public final String getName() {
return this.name;
}
}
java코드를 보면, private로 선언된 변수 name을 getName()이라는 함수를 통해 읽는다는것을 알 수 있다.
getter 와 setter를 프로그래밍 언어 수준에서 제공한다고 생각하면 될듯!!
-전체문법
var <propertyName>[: <PropertyType>] [=<property_initializer>]
[<getter>]
[<setter>]
외부적으로 볼 땐, name이라는 필드에 바로 접근한 것처럼 보이지만
사실은 getter라는 accessor를 통해 접근한 것이다.
custom accessor는 프로퍼티 선언 내부에, 일반 함ㅁ수처럼 선언할 수 있다.
//관습적으로 setter의 파라미터 이름은 value이다. 변경 가능!!
val isEmpty:Boolean
get() = this.size==0
var stringRepresentation : String
get() = this.toString()
set(value){
setDataFromString(value)
}
accessor에 visibility 변경이 필요하거나
accessor에 annotation이 필요한 경우
(accessor인데 visibility를 변경할 이유가 뭐지? 무조건 열려있어야 하는거 아닌가? 이건 더생각해봐야할듯
강의에서는 setter를 private으로 설정할 경우라는데, 음? 그럼 val로 변수를 만들어서 set 못하게 하면 되는거 아닌감?)
var setterVisibility: String = "abc"
private set
var setterWithAnnotation: Any? = null
@Inject set //annotate the setter with Inject
body를 작성해주어도 된다.
var setterVisibility:String = "abc"
private set(value){
field = value
}
코틀린 클래스는 field를 가질 수 없다.
field라는 예약어를 통해 접근할 수 있는, automatic backing field를 제공한다. field는 프로퍼티의 accessor에서만 사용 가능하다.
var counter = 0
set(value){
if(value >= 0) field = value
}
var counter = 0
set(value){
if(value >= 0)field = value
}
val isEmpty : Boolean
get() = this.size == 0
fun main(args:Array<String>){
var obj=Address()
println(obj.isEmpty)
}
class Address{
val isEmpty : Boolean
get(){return isEmpty}
}
public final class Address {
public final boolean isEmpty() {
return this.isEmpty();
}
}
fun main(args:Array<String>){
var obj=Address()
println(obj.isEmpty)
}
class Address{
val isEmpty : Boolean = false
get(){return field}
}
public final class Address {
private final boolean isEmpty;
public final boolean isEmpty() {
return this.isEmpty;
}
}
const val MY_CONST = "CONST" // 이렇게 topLevel이어야 한다.
@Deprecated(MY_CONST)
fun main(args:Array<String>){
var obj=Address()
println(obj.isEmpty)
}
class Address{
val isEmpty : Boolean
get(){return isEmpty}
}
조건
fun main(args:Array<String>){
var obj=Address()
println(obj.data)
}
class Address{
var data : String
init{
data="Kotlin"
}
}
테스트 때문에 init이 아니라 setUp() 함수에서 초기화를 해야하는 경우 이렇게 해야한다.
fun main(args:Array<String>){
var obj=Address()
println(obj.data)
}
class Address{
lateinit var data : String
fun setUp(){
data="나중에"
}
}