로직이 워낙 많아져서 모듈 여러개를 모듈에 넣어서 그 모듈을 extend 하는 방식으로 코드를 키워 나가는 중에, 모듈 선언하는 방식과 로딩 순서에 따라 동작이 다른 듯 하여, 필요한 만큼만 검색, 테스트로 살짝 파봤다.
결론부터 말하자면, lexical scope 을 먼저, 그 후에 inheritance 구조를 타면서 찾는다.
아래 코드는 위 링크에서 뽑아온 코드고, 이렇게 짜야 한다는 뜻은 아니다. 이런 특이한 상황은 마주하지 않고 피하는 것이 최선
module A
module B
PI = 3.14
module C
class E
PI = 3.15
end
class F < E
def get_pi
puts PI
end
end
end
end
end
f = A::B::C::F.new
f.get_pi
> 3.14
lexical scope 를 1차로 확인하고, 그 후에 inheritance hierarchy 를 확인하기 때문에 3.15 대신 3.14 를 얻게 됨.
만약 B 모듈의 PI 선언을 주석처리한다면? 결과는 3.15 가 나온다.
module A
end
module A::B
PI = 3.14
end
module A::B::C
class D
def get_pi
puts PI
end
end
end
d = A::B::C::D.new
d.get_pi
NameError: uninitialized constant A::B::C::D::PI
Did you mean? A::B::PI
A::B::C 처럼 :: (namespace resolution operator) 를 사용해서 선언하게 되면 lexical scope 을 벗어나게 돼서, 위처럼 에러가 난다.
아래처럼 선언하면?
module A
module B
module C
class D
...
3.14 출력.
또, 아래처럼 선언하면?
module A::B
module C
class D
...
3.14 출력.
module A
A_CONSTANT = 1
module B
B_CONSTANT = 2
end
end
module A # open A’s scope
module B # open B’s scope under A
p B_CONSTANT
p A_CONSTANT
end
end
module A::B # open B’s scope without opening A
p B_CONSTANT # B constants are resolved
p A_CONSTANT # This throws a NameError unless A_CONSTANT is defined in B or TOPLEVEL
end
출력 결과는 2, 1, 2
마지막 p 만 에러가 발생한다.
7/31 최초 작성.