2012-02-22 2 views
9

클래스 이름을 알지 못하고 새 클래스를 만들려고합니다. 생성 될 때까지 클래스 이름을 알지 못합니다.동적으로 클래스 만들기

이와 비슷한 것; 가능하면

variable = "ValidClassName" 

     class variable 

     end 

Test = ValidClassName.new 

, 내가 동적으로 새로운 클래스 특성 (및 방법)을 추가하는 방법에 대한 솜 힌트를 주시면 감사하겠습니다.

나는 클래스 '설정'을 불러 오는됩니다, 그들은 같은 것을 볼 것이다 :

title :Person 
attribute :name, String 
attribute :age, Fixnum 

을하지만 해당 명시 적으로 파일을 수용하도록 설계되지 않아야은, 속성은 숫자 결국 다를 수 있습니다 유형.

class Person 
    def initialize(name, age) 

     @name_out = name 
     @age_out = age 
    end 

end 

도움말 :

결국 어떤 식으로 뭔가를 보여야하는 클래스를 생성합니다?

variable = "SomeClassName" 
klass = Class.new(ParentClass) 
# ...maybe evaluate some code in the context of the new, anonymous class 
klass.class_eval { } 
# ...or define some methods 
klass.send(:title, :Person) 
klass.send(:attribute, :name, String) 
# Finally, name that class! 
ParentClass.send(:const_set, variable, klass) 

를 ... 아니면 그냥 평가 후면 사용할 수 있습니다 :

+1

클래스의 소스 코드를 만들고 싶습니까? 또는 소스를 생성하고 런타임에 클래스를 컴파일 /로드하라는 루비에게 알려주고 싶습니까? – ardnew

+1

호기심에서 벗어나서 어떤 문제를 해결하고 있습니까? 이 동적으로 생성 된 클래스를 어떻게 사용할 계획입니까? – ctcherry

+0

내 수업은 yaml 파일에서 objetcs (클래스에 의해 설정된 요구 사항을 충족하는 한)를 인스턴스화하기 위해 사용 된 후에 '프레임'으로 작동해야합니다. YAML은 많은 "사람"을 보유하고 있으며 일부는 요구 사항과 일치하는 속성을 가지고 있습니다. – BSG

답변

23

이 클래스는이 일정에 할당 된 이름을 얻게합니다. 따라서 const_set을 사용하면 일반적인 방식으로 처리하기가 쉽습니다. 예를 들어

, 당신이 할 수있는, 이제 당신이 어떤 속성을 가진 클래스를 구축 할 Struct를 사용하고 싶은 말은하자

name = "Person" 
attributes = [:name, :age] 

klass = Object.const_set name, Struct.new(*attributes) 
# Now use klass or Person or const_get(name) to refer to your class: 
Person.new("John Doe", 42) # => #<struct Person name="John Doe", age=42> 

가 다른 클래스에서 상속하려면 대체 Class.new(MyBaseClass)Struct.new는 말 :

class MyBaseClass; end 

klass = Class.new(MyBaseClass) do 
    ATTRIBUTES = attributes 
    attr_accessor *ATTRIBUTES 
    def initialize(*args) 
    raise ArgumentError, "Too many arguments" if args.size > ATTRIBUTES.size 
    ATTRIBUTES.zip(args) do |attr, val| 
     send "#{attr}=", val 
    end 
    end 
end 
Object.const_set name, klass 
Person.new("John Doe", 42) # => #<Person:0x007f934a975830 @name="John Doe", @age=42> 
+0

klass를 선언하는 동안 오류가 발생합니다. 이름은 상수 여야합니다. 그래서 klass를 2, 3 행으로 대문자로 만들었고 이제는 작동 중입니다. – tebayoso

+0

아, 맞아. 수정 된 예. –

6

코드는 다음과 유사 보일 것

eval <<DYNAMIC 
    class #{name} 
    title :Person 
    attribute :name, String 
    # ...or substitute other stuff in here. 
    end 
DYNAMIC 
+1

미안하지만, 나는 정말로 여기 깊이 내리고있다. 내가 3 살 때처럼 설명해 주시겠습니까 ..? : p – BSG

+1

이렇게 쉽게 이해할 수 있을지 확신하지 못합니다. 두 번째 경우는 아마 이해하기 쉽습니다 :'eval'은 문자열을 취해서 호출시 * 루비 코드처럼 평가합니다. 따라서 런타임에 동적 클래스의 소스 코드로 문자열을 만든 다음 평가합니다. 첫 번째 경우는 새 클래스 객체를 만들고, 원하는 메소드 등을 만들기 위해 일을하고, 이름을 부여합니다. 루비에서는 클래스 객체를 상수에 할당하는 것과 같습니다. –