오늘은 메쏘드와 관련된 몇가지 기본적인 문법들을 정리해보려고 한다.
먼저 매쏘드의 정의! 매쏘드는 당연히 def 메쏘드 이름 ~ end 로 이루어진다. 그런데 매쏘드 이름이 대문자로 시작하면 어떻게 될까? 다음의 예제를 보자
def test
puts "test method"
end
test()
test
def Test
puts "test method"
end
Test()
Test
결과를 관찰하면 알 수 있겠지만 "test method"라는 문자열이 4번 출력되지 않는다. 단지 3번 출력되고 마지막에 경고가 나온다. 경고 메시지는 다음과 같다
test.rb:13: uninitialized constant Test (NameError)
위의 예제의 13번째 줄은 마지막줄이다. 마지막 줄이 무엇이 이상한가? 그렇다. 루비에서는 대문자로 시작하는 것은 constant 로 일단 생각하는 것이다. 위의
test 는 메쏘드로 생각해서 실행시킨것과 대조된다. 처음 루비를 접하면 뒤에 괄호를 하지 않아도 된다는 생각에 나중에는 대문자로 정한 메쏘드까지도 그렇게 할 수 있지만 그렇지가 않다. 루비는 기본적으로 메쏘드의 이름은 소문자로 시작한다고 생각한다. 그러므로 명시적으로 뒤에 괄호를 붙여주지 않는다면 대문자로 시작하는 메쏘드는 호출되지 않는다.
두번째는 메쏘드가 가변인자 받기. 프로그래밍 랭귀지의 대표적인 C언어는 가변인자를 받는 것을 허용한다. 자바와 같은 경우도 버전이 1.4에서 5로 넘어가면서 가변인자를 받을 수 있게 되어 있다. 심지어 자바스크립트도 가변인자를 받을 수 있다. 루비는? 물론 루비도 받을 수 있다. 다음처럼...
def test(*ab)
puts ab.join(", ")
end
test "A","B","C"
결과는 "A, B, C"이다. 루비에서는 이처럼 메쏘드의 인자의 이름 앞에 "*"를 붙여 주어 가변인자를 받도록 하고 있다.
세번째는 메쏘드가 블럭을 호출하기. 메쏘드는 메쏘드를 호출하면서 뒤이어 나온 블럭을 호출할 수 있다. 그렇게 하는 방법은 두가지이다. 다음이 그 예이다
def test1(&block)
block.call
end
def test2
yield
end
test1 do
puts "block"
end
test2 do
puts "block"
end
첫번째는 인자로 받아서 호출하는 것이다. 두번째는 "yield"로 호출하는 것이다. 그런데 블럭을 메쏘드 뒤에 주었는지, 주지 않았는지 어떻게 알 수 있을까? 첫번째의 예제에서는 block라는 인자의 값이 nil인지 확인해보면 된다. 그리고 두번째의 경우에는 "block_given?"이라는 연산을 통해서 알 수 있다. 이 값은 주면 true, 주지 않으면 false를 반환한다.
그러면 블럭에 인자를 주고 블럭이 인자를 받는것은 어떻게 할 수 있는가? 이것역시도 기본적인 일이다. 배열 클래스의 each라는 메쏘드를 어떻게 사용하였는지 기억한다면 쉽게 알 수 있다. 다음이 간단한 예이다.
def test
yield("test func")
end
test do |message|
puts message
end
보는 것처럼 인자를 주는것은 메쏘드를 호출하는 것과 같다. 인자로 받아서 .call을 통해서 호출하는 것도 마찬가지이다. 블럭이 인자를 받기 위해서는 "|"를 사용하며 받는 인자는 ","로 구분하여 여러개도 가능하다. 또한 가변인자를 받는 것도 메쏘드가 하는 것처럼 가능하다
더 나아가 블럭도 하나의 메쏘드처럼 리턴값을 줄 수 있다. 그리고 그것을 호출한 메쏘드는 다른 메쏘드를 호출하여 리턴값을 받듯이 받을 수 있다. 범위 클래스의 "collect"라는 메쏘드는 그 리턴값을 사용하는 대표적인 예이다. 간단히 언급하자면 "collect"라는 메쏘드는 다음과 같이 사용하며 배열을 리턴한다
(1..10).collect { |n| n*2 }
네번째는 메쏘드 호출시 배열의 사용.. 메쏘드를 호출할 때에는 그 메쏘드가 원하는 인자를 넘겨 주어야 한다. 그런데 그 인자를 넘겨줄 때, 인자가 여러개인 경우 배열 하나로 인자들을 넘겨주는 것이 가능하다. 다음이 그 예이다.
def test(a,b)
puts a
puts b
end
test "A", "B"
a = ["A", "B"]
test *a
위에서 test라는 메쏘드를 호출하는데, 처음에는 그대로 인자를 주어서, 두번째는 배열로 주는 것이다. 배열로 인자를 줄 때에는 배열 이름 앞에 "*"를 명시해주어야 한다. 그리고 배열의 길이가 필요한 인자보다 많은 경우에는
in `test': wrong number of arguments (3 for 2) (ArgumentError) 라는 에러를 발생시킨다. 하지만 예상할 수 있듯이 가변인자를 받는 경우라면 에러를 발생시키지 않고 모조리 가변인자에 넘겨준다.
이제 몇가지 문법만 더 정리하면 "
나를 위한 루비"를 시작할 수 있을 것 같다. "
Ruby"카테고리에는
rubyist에 게시할, 루비와 관련해서 다른사람들에게도 도움이 될만한 내용들을 정리했다. 하지만 "
나를 위한 루비"에는 개인적으로 루비를 즐긴 이야기들을 적을 생각이다.