getter와 setter는 객체의 속성 값을 읽고 쓸 수 있게 해 주는 메서드예요. Crystal에는 매크로가 있어서 속성에 대한 getter와 setter를 쉽게 정의할 수 있어요. 매크로는 컴파일 시점에 코드를 생성하는 방법인데, 이는 나중에 매크로 개념에서 다뤄요.
Ruby에서는 이런 메서드를 attr_reader, attr_writer, attr_accessor 메서드로 정의하는데, 겉보기에는 Crystal의 구현과 아주 비슷해요.
Crystal은 이를 getter, setter, property 매크로로 정의해 두었어요.
getter는 인스턴스 변수의 값을 반환하는 메서드를 정의하는 매크로예요.
즉, 인스턴스 변수에 접근하고 싶을 때 (initialize를 제외한 메서드에서) 더 이상 변수 앞에 @를 쓰지 않아도 되고, 대신 getter 매크로가 정의한 메서드를 호출하면 돼요.
getter 매크로는 인스턴스 변수를 쉼표로 구분해서 여러 개 받을 수 있어요.
# This:
class Person
@name : String
@age : Int32
def name
@name
end
def age
@age
end
end
# Is the same as this:
class Person
@name : String
@age : Int32
getter name, :age
end
보다시피, getter를 사용하면 작성하는 코드의 양이 줄고 읽기도 더 쉬워져요. 또한 Crystal은 getter 매크로의 인자로 변수 이름과 심볼을 모두 받는다는 점에서 Ruby와 달라요. 심볼은 나중에 심볼 개념에서 다뤄요.
setter는 인스턴스 변수의 값을 설정하는 메서드를 정의하는 매크로예요.
이 매크로는 그렇게 자주 쓰이지 않고, 보통은 대신 property 매크로를 사용해요.
이때 만들어지는 메서드는 name_of_method=처럼 생겼는데, 바로 이 = 덕분에 속성 값을 설정할 수 있어요.
이 메서드 정의는 조금 특이한데, 메서드가 받는 인자가 = 기호 뒤에 오기 때문이에요.
Crystal의 다른 여러 특별한 메서드도 이 문법을 사용해요. + 메서드가 그렇죠.
getter 매크로와 마찬가지로, setter를 정의한 뒤 인스턴스 변수의 값을 바꾸고 싶을 때는 setter 매크로가 정의한 메서드를 호출하면 돼요.
# This:
class Person
@name : String
@age : Int32
def name=(name : String)
@name = name
end
def age=(age : Int32)
@age = age
end
end
# Is the same as this:
class Person
@name : String
@age : Int32
setter name, :age
end
property는 인스턴스 변수에 대해 getter와 setter를 모두 정의하는 매크로예요.
class Person
@name : String
@age : Int32
property name, :age
end
이 연습 문제에서는 저울을 모델링해요.
저울은 초기화될 때, 판매되는 지역에 따라 다른 공장 출하 설정을 참조해야 해요. 따라서 저울은 정밀도와 미터법 또는 야드파운드법 여부를 가지고 초기화될 수 있어야 해요.
precision(Int32형)과 metric(Bool형) 두 인자를 받는 WeighingMachine#initialize 메서드를 구현해요. metric 인자가 true이면 미터법을, 그렇지 않으면 야드파운드법을 사용해야 한다는 뜻이에요. 또한 initialize 메서드는 인스턴스 변수 @weight를 0.0으로 설정해야 해요.
precision = 3
metric = true
vm = WeighingMachine.new(precision, metric)
다양한 요구에 맞추기 위해, 각 저울은 정밀도(소수 구분 기호 뒤의 자릿수)로 사용자 정의할 수 있어요.
저울의 정밀도를 반환하는 WeighingMachine#precision 게터 메서드를 구현해요.
precision = 3
metric = true
vm = WeighingMachine.new(precision, metric)
vm.precision
# => 3
무게를 가져오고 설정할 수 있도록 WeighingMachine#weight 프로퍼티를 구현해요:
precision = 3
metric = true
wm = WeighingMachine.new(precision, metric)
wm.weight = 60.5
wm.weight
# => 60.5
wm.weigh
# => 60.5
단위를 설정할 수 있도록 WeighingMachine#metric= 프로퍼티를 구현해요. 이 프로퍼티는 불리언 값을 받아야 해요.
precision = 3
metric = true
wm = WeighingMachine.new(precision, metric)
vm.weight = 60.5
wm.metric = false
vm.weigh
# => 133.377
Exercism에 가입하고 Crystal 트랙을 개념 26개연습 문제 142개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.