// 상속 가능한 클래스를 위해 open 사용
open class Human (var name: String="홍길동", var age: Int) { // 주생성자
open fun play() = println("name: $name")
fun sing(vol: Int) = println("Sing age: $age")
}
// 주 생성자를 사용하는 상속
class Woman (name: String, age: Int) : Human(name, age) {
fun singHitone() = println("Happy Song!") // 새로 추가된 메서드
override fun play() = println("Woman name: $name")
}
// 부 생성자를 사용하는 상속
class Man : Human {
val race: String
constructor(name: String, age: Int, race: String) : super(name, age) {
this.race = race // 새로 추가된 프로퍼티
}
}
fun main() {
var woman = Woman("옥분이", 22)
woman.play()
var man = Man("옥철이", 20, "아시아")
}
open class Human {
fun play() { println("Human.play()") }
open fun sing() { println("Human.sing()") }
open fun sing2() { println("Human.sing2()") }
}
open class Animal01 : Human(){
override fun sing(){ println("Animal01.sing()") }
final override fun sing2(){ println("Animal01.sing2()") }
}
open class Animal02 : Animal01(){
override fun sing(){ println("Animal02.sing()") }
}
fun main() {
var animal = Animal02()
animal.play() // Human.play()
animal.sing() // Animal02.sing()
animal.sing2() // Animal01.sing2()
}
// 주 생성자에 3개의 매개변수 정의
class User(_id: Int, _name: String, _age: Int) {
// 프로퍼티들
val id: Int = _id // 불변 (읽기 전용)
var name: String = _name // 변경 가능
var age: Int = _age // 변경 가능
}
class User(val id:Int, var name:String, var age:Int) { // 프로퍼티들
}
class Person {
private var _name: String = ""
var name: String
get() = _name
set(value) {
_name = value
}
}
fun main() {
val person = Person()
person.name = "John"
println(person.name)
}
Kotlin에서 프로퍼티(property)는 값을 저장하는 backing field와 그 값을 읽고 쓸 수 있는 getter와 setter로 구성됩니다. backing field를 사용하지 않는 경우, getter와 setter에서 직접 값을 저장하거나 반환할 수 있습니다.
하지만 이러한 방식으로 프로퍼티를 구현할 경우, 일부 예상치 못한 동작이 발생할 수 있습니다. 예를 들어, 아래와 같은 클래스가 있다고 가정해보겠습니다.
class Person {
var name: String = ""
set(value) {
println("Setting name to $value")
field = value
}
get() {
println("Getting name")
return "Mr. $field"
}
}
위 코드에서는 name 프로퍼티에 getter와 setter 함수를 구현하고 있습니다. 하지만 이 때 backing field를 사용하지 않고, getter에서는 "Mr. "을 붙여서 반환하고 있습니다.
이 상태에서 Person 객체를 생성하고, name 프로퍼티를 두 번 읽으면 다음과 같은 결과가 출력됩니다.
fun main() {
val person = Person()
person.name = "John"
println(person.name)
println(person.name)
}
Setting name to John
Getting name
Mr. John
Getting name
Mr. John
이 결과에서 알 수 있듯이, getter 함수에서 field 대신에 직접 "Mr. "과 field를 조합하여 반환하면, 호출시 예상했던 John의 이름이 아닌 앞에 Mr.이 붙은 예상치 못한 결과를 얻게 됩니다.
따라서 Kotlin에서는 backing property를 사용하여 getter와 setter 함수를 구현하는 것이 좋습니다. 이렇게 하면 예상한 대로 동작하며, 코드의 가독성과 유지 보수성이 향상됩니다.