2011년 6월 2일 목요일

Modules

Modules
모듈은 메서드와 클래스, 상수를 함께 하나로 묶는 수단이다.
  • 모듈은 Namespaces을 제공해서 이름이 충돌하는 것을 막아준다.
  • 모듈은 mixin 기능을 구현하는데 사용한다.


Namespaces
모듈은 Namespace을 정의하는데, 이것은 다른 메서드나 사웃에 의해 방해 받을 염려 없이 메서드와 상수를 정의할 수 있는 일종의 sand box다.

module Trig
 PI = 3.141592654
 def Trig.sin(x)
  # ..
 end
 def Trig.cos(x)
  # ..
 end
end

module Action
 VERY_BAD = 0
 BAD   = 1
 def Action.sin(badness)
# ...
 end
end

모듈 상수의 이름은 클래스 상수처럼 첫 문자를 대문자로 한다. 메서드 선언 또한 비슷하다. 모듈 메서드는 클래스 메서드 처럼 정의한다.
다른 프로그램이 모듈을 이용할 경우 모듈 파일을 불러와서 적절한 이름으로 참조하면 된다.

require "trig"
require "action"
y = Trig.sin(Trig::PI/4)
wrongdoing = Action.sin(Action::VERY_BAD)

클래스 메서드 처럼, 모듈의 이름과 점(.)을 메서드 이름 앞에 붙여서 모듈 메서드를 호출한다. 그리고 상수는 모듈의 이름과 두 개의 콜론(:)을 이용하여 접근한다.

Mixins
모듈은 클래스가 아니기 때문에 인스턴스를 가질 수 없다. 하지만 클래스 선언에 모듈을 include 할 수 있다. 모듈을 포함하면 해당 모듈의 모든 인스턴스 메서드가 클래스 인스턴스 메서드 처럼 동작한다. 이를 Mixin이라 하며 mixin된 모듈은 실제로 일종의 상위 클래스처럼 동작한다.

module Debug  
 def whoAmI?  
"#{self.type.name} (\##{self.id}): #{self.to_s}"  
 end  
end  
class Phonograph  
 include Debug  
 # ...  
end  
class EightTrack  
 include Debug  
 # ...  
end  
ph = Phonograph.new("West End Blues")  
et = EightTrack.new("Surrealistic Pillow")  

ph.whoAmI?  » "Phonograph (#537766170): West End Blues"  
et.whoAmI?  » "EightTrack (#537765860): Surrealistic Pillow"  

루비의 include 구문은 단지 해당 모듈에 대한 참조를 만들 뿐이다. 만일 모듈이 분리된 다른 파일에 있을 경우 include를 사용하지 던에 해당 파일을 require 해야 한다.
루비의 include는 단순히 클래스에 모듈의 인스턴스 메서드를 복사하는 것이 아니다. include는 클래스에 포함될 모듈에 대한 참조를 만든다. 만일 여러 클래스가 하나의 모듈을 포함할 경우, 이 클래스들은 모두 같은 모듈을 참조하게 된다. 그리고 프로그램 실행할 때 그 모듈의 메서드 정의를 수정하면, 그 모듈을 include하는 모든 클래스는 새로운 동작을 수행한다.

Instance Variables in Mixins
루비에서 인스턴스 변수는 "@" 이 앞에 붙은 변수가 처음 쓰일 때 현재 객체인 self에 인스턴스 변수를 만든다. 믹스인에 적용해보면 클라이언트 클래스에 섞은 모듈이 클라이언트 객체에 인스턴스 변수를 만들고 attr_reader 등의 메서드를 이용해서 이 인스턴스 변수를 위한 접근자까지 만들어 준다는 것을 뜻한다.  대부분의 경우에 믹스인되는 모듈이 자신만의 인스턴스 데이터를 가지거나 하지 않는다. 접근자를 사용해서 클라이언트 객체로부터 데이터를 얻어오는 것이 일반적이다. 하지만 믹스인 자체가 상태를 가지길 원하는 경우, 그 인스턴스 변수는 시스템에 있는 다른 어떠한 믹스인과도 구별되는 유일한 이름을 가져야 한다.

Including Other Files
모듈을 새로 만드는 프로그램에 통합할 때 두 개의 구문을 사용할 수 있다. load, require 이다.

load "filename.rb"

require "filename"
load 메서드는 실행 될 때 마다 해당 이름을 가지 루비 소스코드를 포함한다. require는 해당 파일을 단 한번만 로드한다.
불러온 파일 안에서 정의한 지역 변수는 그것을 load나 require 한 곳에서는 사용할 수 없다.
load와 require를 이용하여 로드되는 파일 또한 다른 파일을 포함할 수 있고, 그 파일도 다른 파일을 포함할 수 있다.
require는 if 문 안에 있을 수 있고 실행 중 만들어진 파일 이름 문자열을 이용할 수도 있다.
load는 무조건 해당 소스를 로드하므로, 프로그램이 시작된 후 바뀐 소스를 다시 불러오는데 이용 할 수 있다.

댓글 없음:

댓글 쓰기

블록체인 개요 및 오픈소스 동향

블록체인(block chain) 블록체인은 공공 거래장부이며 가상 화폐로 거래할때 발생할때 발생할 수 있는 해킹을 막는 기술. 분산 데이터베이스의 한 형태로, 지속적으로 성장하는 데이터 기록 리스트로서 분산 노드의 운영자에 의한 임의 조작이 불가...