2014-09-27 2 views
1
class Foo 
end 

class_name = 'Foo' 
f = eval(class_name).new 
#<Foo:0x007fd3e273ed68> 

이 예에서는 Foo의 예상 인스턴스를 만듭니다.Ruby에서 변수로 객체를 인스턴스화하는 방법은 무엇입니까?

클래스가 정의 될 것으로 예상되지만 class_name에 정의 된 클래스의 개체를 인스턴스화하려고합니다.

class_name의 값은 사용자로부터오고, 그래서 위의 코드는 매우 나쁜 아이디어 ™입니다 ...

답변

1

클래스는 특별한 것이 아닙니다. 이것은 변수에 할당 된 객체이거나, 보여준 코드의 경우에는 상수입니다. Object#instance_variable_get, Module#class_variable_get, Binding#local_variable_get, Thread#thread_variable_get, 또는이 경우 Module#const_get에 적용 할 수있는 하나 :

class Foo; end 

class_name = 'Foo' 
foo = Object.const_get(class_name).new 
#=> #<Foo:0x007fd3e273ed68> 

foo = self.class.const_get(class_name).new 
#=> #<Foo:0x007fd3e273ed68> 
그래서, 당신은 당신이 다른 개체에 사용 하듯이 변수에서 클래스를 검색하기 위해 같은 메타 프로그래밍 방법을 사용할 수 있습니다

참고 다른 두 답변의 코드는 실수로 작동 : 그들은 당신이 실제로Object에서 ObjectModule 상속에 Foo 정의가 있기 때문에에만 작동 Module 클래스의 맥락에서 Foo을 찾아보십시오. 당신이 상위에 있지만 Module의 형제에없는 Foo을 정의 한 경우, 다른 두 답변의 코드는 작동하지 않을 것입니다 :

module Bar; class Foo; end end 

Module.const_get(:Foo) 
# NameError: uninitialized constant Module::Foo 

Bar.const_get(:Foo) 
# => Bar::Foo 

정상적인 일정 조회 것이라고 같은 방식으로 동작하는 const_get를 원하는 경우 , 당신은 그것을 실제로 찾아보기를 원하는 클래스/모듈에서 호출해야하며 임의의 클래스에서는 호출 할 필요가 없습니다.

+0

와우, 이것이 내가 찾고있는 대답이다. 고맙습니다. Metaprogramming에서 권장하는 리소스가 있습니까? –

+1

루비 프로그래머는 메타 프로그래밍을 특별한 것으로 생각하지 않습니다. 그것은 정상적인 프로그래밍의 자연스러운 부분이므로 일반적으로 특수한 리소스를 쓰는 것에 대해 생각하지 않습니다. Ruby 프로그래밍을위한 모든 리소스는 메타 프로그래밍을 다루기 시작합니다. 'attr_accessor'는 메소드를 생성하는 메소드로, attr_accessor를 사용할 때마다 메타 프로그래밍을 수행합니다. 그러나, [_why 운 좋은 뻣뻣한] (https://wikipedia.org/wiki/Why_the_lucky_stiff)의 글은, 당신이 그의 독특한 스타일에 탐닉 할 수 있다면, 메타 프로그래밍을 설명하는 데 능숙합니다. –

+1

예를 들어 Ruby * (http://mislav.uniqpath.com/poignant-guide/), 특히 [* Dwemthy 's Array *] (http : //mislav.uniqpath.(Ruby 메타 프로그래밍을 사용하여 플레이 한 던전 게임!) 게다가, 항상 Paolo Perrotta의 [Rubet * Metaprogramming] 책 (https://pragprog.com/book/ppmetr2/metaprogramming-ruby)이 있습니다. -2). 그러나 루비에서 프로그래밍을 통해 Ruby Metaprogramming을 실제로 배웠기 때문에 이러한 리소스 중 일부는 말할 수 없습니다. 그렇게하는 것이 자연 스럽기 때문입니다. –

2

체크 아웃 Module::const_get. 이름에서 알 수 있듯이 물론


class Foo 
end 

class_name = 'Foo' 
myClass = Module.const_get(class_name) 
myClass.new 

, 당신은 상수의 어떤 종류를 얻기 위해 이것을 사용할 수 있습니다. < 1.9 :

SOME_CONST = 5 
Module.const_get('SOME_CONST').is_a? Class # => false 
Module.const_get('String').is_a? Class  # => true 
1

const_get이 클래스에

Module.const_get(:Foo).new 

또는

Module.const_get('Foo').new 

주에 대한 참조를 얻을 수 있습니다 : 그래서 당신은 클래스 다시 얻고 있는지 확인하는 것이 현명 수 있습니다 현재 모듈 만 검색합니다.

관련 문제