Kotlin: 함수와 프로퍼티

4rk·2023년 2월 25일
0

I. 서론

우테코 Level 1을 수행하면서 클래스를 체계적으로 작성할 수 있을까 고민에 빠지고 있다. 그러던 도중 기능 구현에 있어서 프로퍼티와 함수중 어떤 것을 고르면 좋을지 생각해보기 시작했고 마음에 와닿는 블로그 글을 발견하여 참고하고 추가하여 정리해 보고자 한다.

II. 함수와 프로퍼티

전체적으로 보면 아래와 같이 정리될 수 있다.

  • 프로퍼티(property)상태(state)를 표현한다.
  • 함수(function)행동(behaviour)을 표현한다.

III. 프로퍼티

먼저 프로퍼티에 대해서 살펴보자면 객체(object)의 상태를 표현할 수 있는 데이터 구조로 나타낼 수 있다.
예제로 Person이라는 Class를 들어보자면,
현재 name, lastName, weight라는 프로퍼티들이 존재하고 이들은 Person의 상태를 표현하고 있다.
그리고 run(), walk(), weight()라는 메소드들이 존재하며 이들은 Person의 행동을 표현하고 있다.

프로퍼티

class Person(var name: String, var lastName: String, var weight: Double)

함수

class Person () {
    fun run() { /*doSth*/ }
    fun walk() { /*doSth*/ }
    fun jump() { /*doSth*/ }
}

IV. 파생된 프로퍼티(derived properties)

이뿐만이 아니라 파생된 프로퍼티(derived properties)도 추가될 수 있다.
아래의 예제는 fullName이라는 프로퍼티가 namelastName으로 파생된 것을 볼 수 있다.

class Person (var name:String, var lastName: String, var weight:Double) {
	val fullName = "$name $lastName"

파생된 프로퍼티의 문제점

이제 추가로 함수와 프로퍼티에 대해서 고민하게 되는 경우가 발생하게 된다.
fullName이라는 것은 namelastName에서 파생된 것이기 때문에 객체가 생성된 이후에 두 프로퍼티중에 하나가 변경된다면 fullName은 제 역할을 하지 못할 것이다.

해결 방법

이를 해결 하기 위해서 아래의 코드와 같이 프로퍼티에서 getter를 사용하면 된다.

class Person(var name: String, var lastName: String, var weight: Double) {
	val fullName
    	get() = "$name $lastName"
}

V. 함수

함수는 객체가 할 수 있는 행동들을 말하는 것으로 아래의 코드와 같이 사람이 뛰거나 것거나 점프한다는 행위들을 표현 할 수 있다.

class Person () {
    fun run() { /*doSth*/ }
    fun walk() { /*doSth*/ }
    fun jump() { /*doSth*/ }
}

함수 사용시 주의점

추가로 아래의 코드와 같이 점프라는 것은 weight라는 프로퍼티를 변화시키고 있다. 이렇게 함수를 사용 할 때에는 부수효과(side effect)의 영향이 있는 상태 변화가 있을 수있다고 알리는 것이 중요하다.

class Person (var name:String, var lastName:String, var weight:Double) {
    fun jump() { 
        weight -= 0.1   
    }
}

자바 프로그래머들이 코틀린으로 넘어왔을 경우의 문제점

자바 프로그래머들은 setgetprefix하여 메소드들을 만들게 되는데 아래의 예제와 같이 단순히 값을 반환하는 경우 코틀린에서는 프로퍼티로 대신 정의할 필요가 있다.

// GOOD
class Person(var name: String, var lastName: String, var weight: Double) {
	val fullName
    	get() = "$name $lastName"
}
// BAD
class Person (var name: String, var lastName: String) {
    private var weight:Double = 0

    fun setWeight(weight:Double) {
        this.weight = weight
    }
    fun getWeight(): Double {
        return weight
    }
    get getFullName(): String {
    	return "$name $lastName"
	}
}

VI. 꿀팁

아직도 헷갈린다면?

만약에 아직도 메소드와 프로퍼티의 구분 짓기가 힘들다면 내부에서 어떻게 동작하는지 잊어보도록하고 외부에서 접근 할 때 어떻게 보이는지 확인해 보자

person.name = "Igor"
person.weight = 79
person.jump()
person.jump()
person.jump()

프로퍼티 위임(property delegates)

프로퍼티에는 위임이라는 아주 유용한 기능이 있는데 코드 재사용성을 높여준다는 장점이 있다. 우리가 변수를 초기화를 할 때는 lazy 위임을 속성 값이 변경될 때마다 일부 작업을 수행 할때는 observable 위임을 마지막으로 커스텀 위임을 통해 다른 오브젝트들을 보관 할 수도 있다.

블로그에 제안된 프로퍼티 가이드 라인

  • 예외를 발생시키면 안된다.
  • 계산하는데 가벼워야한다.(아니면 처음 실행 후에 캐싱)
  • 내부 상태가 변하지 않으면 여러 호출에 대한 반환이 같은 결과가 나와야 한다.

참고

profile
4rk의 프로그래밍 스터디

1개의 댓글

comment-user-thumbnail
2023년 2월 25일

저도 궁금하던 내용인데, 글이 잘 정리되어 있어서 좋네요!!
좋은 글 감사합니다~~!

답글 달기