이틀째 접어든 루비...
처음에 루비에서 클래스를 만들고 접근해서 사용하다보면... 클래스의 속성에 접근할 방법이 보이질 않는다. 하지만 방법이 없어서가 아니라 다른 랭귀지들과 약간 다르기 때문이다.
class Test
def x
10
end
end
위와같은 클래스가 있다고 가정해보자. 그러면 위의 클래스의 인스턴스에 접근자를 사용해서 x를 호출하면 일반적인(?) 랭귀지와는 달리 뒤에 괄호를 붙이거나 할 필요가 전혀없다. 그냥 그 자체로 호출이 되고 10을 리턴하게 된다. 그러므로 다음과 같은 클래스가 있다면.. x라는 속성에 접근할 방법이 없다. 접근자를 사용해서 x를 호출하면 매쏘드를 찾기 때문이다.
class Test
def initialize
@x = 10
end
end
그러면 이 경우에 있어서 어떻게 해야 할까? 물론 당연한 이야기지만 방법이 제공된다. 그리고 여타 다른 랭귀지보다 프로그래머를 즐겁게 해 줄 방법도 제공된다. 그 방법을 간단히 정리해본다
먼저 간단히 읽기 위해 접근하는 방법이 있다. 다음의 코드처럼 그냥 메쏘드를 만들어주면 된다.
class Test
def initialize
@x = 10
end
def x
@x
end
end
이렇게 하면 접근자를 사용해 x를 호출하면 위 x라는 메쏘드가 호출되어 "@x"값을 리턴한다. 하지만 단지 접근만을 하려는데 위처럼 하는 것은 조금 지나쳐 보인다. 그래서 루비는 다음과 같은 방법을 제공한다.
class Test
attr_reader :x
def initialize
@x = 10
end
end
위에서 굵게 표시된 부분이 바로 접근을 가능하게 해주는 부분이다. 그렇게 하면 단지 읽기만 접근이 가능하다. 그렇다면 쓰기는 어떻게 해야 할까? 적당히 짐작해볼 수 있듯이 attr_reader에서 reader을 writer로 바꿔주면 된다. 아래는 그 예이다.
class Test
attr_reader :x
attr_writer :x
def initialize
@x = 10
end
end
t = Test.new
t.x = 20
puts t.x
당연한 이야기지만 쓰기 접근이 되므로 20이 출력된다. 그런데 여기에 더해 루비는 함수를 만들어서 접근하는 것을 지원한다. 아래가 그 예이다. 아래의 예는 위와 동일한 결과를 준다.
class Test
attr_reader :x
def initialize
@x = 10
end
def x=(x)
@x = x
end
end
t = Test.new
t.x = 20
puts t.x
그러면 이것은 어디에 쓸까? 처음에 접근을 위한 함수를 만들때와 그 함수를 사용해서 속성을 가공해서 돌려줄 수 있듯이 이 함수 역시 속성에 값을 입력할 때 그 값을 가공해서 저장할 수 있다.
Programming Ruby의
Classes, Objects, and Variables부분에 보면 그 예가 나온다. 음악의 길이를 입력받을 때 내부적으로 초로 처리하더라도 분으로 입력받게 하는 접근자를 만드는 예이다. 이와같이 조금만 생각해보면 위와같은 메쏘드를 이용한 접근이 얼마나 유용한지 알 수 있다.
잠깐!위의 책, 즉 Programming Ruby를 보면 루비에서는 클래스 내에서 속성과 변수를 구분하고 있다는 것을 알 수 있다. 클래스에서 "@"를 하나 사용하고 있는 것들은 속성이고 두개 사용하고 있는 것들은 변수라고 부른다. 무엇인지 알고 보면 당연히 그래야 한다. 아무튼 그게 뭔지 알아보자. 아래의 예를 보면 그것이 무엇인지를 명확히 알 수 있다
class Test
@@x=0
def initialize
@x=0
end
def out
@x+=1
@@x+=1
puts "attribute is #@x, class variable is #@@x"
end
end
t1 = Test.new
t2 = Test.new
t1.out
t2.out
t1.out
t2.out
위의 예에 대한 결과는 아래와 같다.
attribute is 1, class variable is 1
attribute is 1, class variable is 2
attribute is 2, class variable is 3
attribute is 2, class variable is 4
이 결과를 보면 느낌을 받을 것이다. 바로 루비에서 클래스 변수라고 부르는 것은 자바와 같은 언어에서는 정적 변수라는 것과 같다는 것이다. 인스턴스를 생성해도 그 값은 언제나 유지되고 전체 모든 인스턴스에서 공유된다는 것이다. 그리고 정적 메쏘드는 클래스 메쏘드라고 불린다. 그것을 선언하는 방법과 사용하는 것에 대한 예는 아래와 같다.
class Test
@@x=0
def initialize
@x=0
end
def out
@x+=1
@@x+=1
puts "attribute is #@x, class variable is #@@x"
end
def Test.outClassVariableX
puts "class vartiable is #@@x"
end
end
t1 = Test.new
t2 = Test.new
t1.out
t2.out
t1.out
t2.out
Test.outClassVariableX
결과는 다음과 같다
attribute is 1, class variable is 1
attribute is 1, class variable is 2
attribute is 2, class variable is 3
attribute is 2, class variable is 4
class vartiable is 4
루비는 배워볼 수록 재미있는 언어다... 다음이 기대가 된다..