[루비 사용자 가이드] 메소드

루비/레일스 프로그래밍/루비 사용자 가이드 2007.04.30 17:09

메소드란 무엇일까요? OO프로그래밍에서는 객체의 바깥에서 데이터를 직접 조작하는 것을 생각하지 않습니다. 대신 객체는 (그렇게 해 달라고 제대로 요청받았을 경우) 자신을 어떻게 조작할지에 대한 지식을 가지고 있습니다. 우리는 객체에 메시지를 전달하고, 그 메시지가 어떤 종류의 동작이나 의미있는 답을 일으킨다고 이야기하기도 합니다. 이런 일련의 일들은 객체 내부가 실제로 어떻게 동작하는지에 대해서 알거나, 주의를 기울일 필요 없이 이루어져야 합니다. 객체가 수행하도록 요청할 수 있는 동작(혹은 객체가 이해할 수 있는 메시지)을 객체의 메소드라 합니다.

루비에서는 도트 표기법을 사용해 메소드를 호출합니다(C++이나 자바와 동일합니다). 메시지를 전달받는 객체는 도트의 왼쪽에 표시됩니다

ruby> "abcdef".length
   6

직관적으로, 이 스트링 객체는 얼마나 긴지 질문을 받고 있습니다. 기술적으로, 우리는 "abcdef" 객체의 length 메소드를 호출하고 있습니다.

다른 객체는 length를 조금 다르게 해석하거나, 이해하지 못할 수도 있습니다. 어떤 메시지에 응답 하는 방법을 결정하는 것은 프로그램 실행 도중, 객체가 메시지를 받는 시점에 이루어지며, 어떤 동작이 일어나는지는 변수가 어떤 객체를 가리키고 있느냐에 따라 변할 수 있습니다.

ruby> foo = "abc"
   "abc"
ruby> foo.length
   3
ruby> foo = ["abcde", "fghij"]
   ["abcde", "fghij"]
ruby> foo.length
   2

length가 의미하는 바는 그 메시지를 받는 객체가 어떤 것이냐에 따라 달라 질 수 있습니다. 앞의 예에서 처음 foo 에 길이를 물어봤을 때, foo 가 단순한 스트링을 참조하고 있었고, 의미 있는 답은 한 가지 밖에 없었습니다. 두 번째 foo 는 배열을 가리키고 있고, 이때 논리적으로 가능한 답은 2 아니면 5나 10일 것입니다. 하지만 가장 일반적으로 수긍할만한 답은 물론 2 입니다(원한다면 다른 종류의 답을 낼 수도 있습니다).

ruby> foo[0].length
   5
ruby> foo[0].length + foo[1].length
   10

여기서 명심해야 할 것은 배열 객체가 배열이 되는 것이 어떤 의미인지를 알고 있다는 것입니다. 루비의 데이터는 그런 지식을 가지고 있기 때문에 외부의 요청을 적절한 방법으로 만족시켜줄 수 있습니다. 이런 구조는 프로그래머가 수 없이 많은 구체적인 함수 이름을 외우는 것을 막아줍니다. 왜냐하면 우리가 일상 언어로 표현할 줄 아는 개념에 대응하는, 상대적으로 적은 갯수의 메소드를 여러 종류의 데이터에 적용할 수 있고, 그 결과도 우리가 예상할 수 있는 것과 같을 것이기 때문입니다. 이런 OO 프로그래밍 언어의 특징을 (내 생각에 자바는 이런 부분을 별로 개발하지 못했습니다) 다형성(polymorphism)이라고 부릅니다.

객체가 이해할 수 없는 메시지를 받게 되면, 에러가 "발생(raise)"됩니다:

ruby> foo = 5
   5
ruby> foo.length
ERR: (eval):1: undefined method `length' for 5(Fixnum)

따라서 어떤 객체가 메소드를 처리하는 방법을 알 필요는 없지만, 그 객체가 어떤 메소드를 처리할 수 있는 지를 아는 것이 필요합니다.

메소드에 인자가 주어질 때는 보통 다음과 같이 괄호로 그 인자를 둘러쌉니다.

object.method(arg1, arg2)

하지만, 모호성이 없는 경우에는 괄호를 생략할 수도 있습니다.

object.method arg1, arg2

루비에는 self라는 특별한 변수가 있습니다. 그 변수는 메소드를 처리하는 객체를 참조합니다. 객체가 자기 자신의 메소드를 호출하는 일은 너무 자주 일어나기 때문에, 편의를 위해서 자기 자신의 메소드를 호출할 경우 "self."를 생략할 수 있습니다:

self.method_name(args...)

는 다음과 동일합니다.

method_name(args...)

전통적으로 함수 호출(function call)이라고 생각해 왔던 것들은 루비에서 단지 짧게 표기된 self에 대한 메소드 호출일 뿐입니다. 이렇게 해서 루비는 순수한 객체지향 언어로 남아있을 수 있습니다. 이런 함수같은 메소드는, 루비의 함수 호출이 어떻게 객체의 메소드 호출인지 알지 못하는 사람들이 편하게 사용할 수 있도록, 다른 프로그래밍 언어에서의 함수와 매우 유사하게 동작합니다. 원한다면 마치 객체의 메소드가 아닌 것 처럼 함수에 대해 말할 수 있습니다.


Trackbacks 0 : Comments 0

Write a comment