클래스 이름이있는 동적 클래스 정의
Ruby에서 이름으로 클래스를 동적으로 정의하려면 어떻게해야합니까?
다음과 같은 것을 사용하여 이름 없이 동적으로 클래스를 만드는 방법을 알고 있습니다 .
dynamic_class = Class.new do
def method1
end
end
그러나 클래스 이름을 지정할 수 없습니다. 나는 클래스를 동적으로 생성 할 로 이름을.
여기 제가하고 싶은 일의 예가 있지만 물론 실제로는 작동하지 않습니다.
(클래스의 인스턴스가 아니라 클래스 정의를 생성한다는 점에 유의하십시오)
class TestEval
def method1
puts "name: #{self.name}"
end
end
class_name = "TestEval"
dummy = eval("#{class_name}")
puts "dummy: #{dummy}"
dynamic_name = "TestEval2"
class_string = """
class #{dynamic_name}
def method1
end
end
"""
dummy2 = eval(class_string)
puts "dummy2: #{dummy2}" # doesn't work
실제 출력 :
dummy: TestEval
dummy2:
원하는 출력 :
dummy: TestEval
dummy2: TestEval2
================================================ ====
답변 : sepp2k의 방법을 사용하는 완전히 동적 인 솔루션
dynamic_name = "TestEval2"
Object.const_set(dynamic_name, Class.new) # If inheriting, use Class.new( superclass )
dummy2 = eval("#{dynamic_name}")
puts "dummy2: #{dummy2}"
클래스의 이름은 단순히 그것을 참조하는 첫 번째 상수의 이름입니다.
즉 내가 할 경우 myclass = Class.new
다음 MyClass = myclass
클래스의 이름이 될 것입니다 MyClass
. 그러나 MyClass =
런타임까지 클래스 이름을 모르면 할 수 없습니다 .
따라서 대신 Module#const_set
const 값을 동적으로 설정하는를 사용할 수 있습니다 . 예:
dynamic_name = "ClassName"
Object.const_set(dynamic_name, Class.new { def method1() 42 end })
ClassName.new.method1 #=> 42
나도 이것으로 엉망이되고있다. 제 경우에는 ActiveRecord :: Base에 대한 확장을 테스트하려고했습니다. 클래스를 동적으로 생성 할 수 있어야했고 활성 레코드가 클래스 이름을 기반으로 테이블을 조회하기 때문에 해당 클래스는 익명이 될 수 없습니다.
이것이 귀하의 사례에 도움이되는지 확실하지 않지만 다음은 제가 생각 해낸 것입니다.
test_model_class = Class.new(ActiveRecord::Base) do
def self.name
'TestModel'
end
attr_accessor :foo, :bar
end
ActiveRecord에 관한 한 self.name을 정의하는 것으로 충분합니다. 클래스가 익명이 될 수없는 모든 경우에 실제로 작동 할 것이라고 생각합니다.
(I've just read sepp2k's answer and I'm thinking his is better. I'll leave this here anyway.)
I know this is a really old question, and some other Rubyists might shun me from the community for this, but I am working on creating a very thin wrapper gem that wraps a popular java project with ruby classes. Based on @sepp2k's answer, I created a couple helper methods because I had to do this many, many times in one project. Note that I namespaced these methods so that they were not polluting some top-level namespace like Object or Kernel.
module Redbeam
# helper method to create thin class wrappers easily within the given namespace
#
# @param parent_klass [Class] parent class of the klasses
# @param klasses [Array[String, Class]] 2D array of [class, superclass]
# where each class is a String name of the class to create and superclass
# is the class the new class will inherit from
def self.create_klasses(parent_klass, klasses)
parent_klass.instance_eval do
klasses.each do |klass, superklass|
parent_klass.const_set klass, Class.new(superklass)
end
end
end
# helper method to create thin module wrappers easily within the given namespace
#
# @param parent_klass [Class] parent class of the modules
# @param modules [Array[String, Module]] 2D array of [module, supermodule]
# where each module is a String name of the module to create and supermodule
# is the module the new module will extend
def self.create_modules(parent_klass, modules)
parent_klass.instance_eval do
modules.each do |new_module, supermodule|
parent_klass.const_set new_module, Module.new { extend supermodule }
end
end
end
end
To use these methods (note that this is JRuby):
module Redbeam::Options
Redbeam.create_klasses(self, [
['PipelineOptionsFactory', org.apache.beam.sdk.options.PipelineOptionsFactory]
])
Redbeam.create_modules(self, [
['PipelineOptions', org.apache.beam.sdk.options.PipelineOptions]
])
end
WHY??
This allows me to create a JRuby gem that uses the Java project and would allow the open source community and I to decorate these classes in the future, as necessary. It also creates a more friendly namespace to use the classes in. Since my gem is a very, very thin wrapper, I had to create many, many subclasses and modules to extend other modules.
As we say at J.D. Power, "this is apology-driven development: I'm sorry".
How aboutthe following code:
dynamic_name = "TestEval2"
class_string = """
class #{dynamic_name}
def method1
end
end
"""
eval(class_string)
dummy2 = Object.const_get(dynamic_name)
puts "dummy2: #{dummy2}"
Eval doesn' retun the runtime Class object, at least on my PC it doesn't. Use Object.const_get to get the Class object.
참고URL : https://stackoverflow.com/questions/4113479/dynamic-class-definition-with-a-class-name
'code' 카테고리의 다른 글
데이터 프로토콜 URL 크기 제한 (0) | 2020.11.07 |
---|---|
C # Linq Where Date Between 2 Dates (0) | 2020.11.07 |
임의의 문자열이 유효한 파일 이름인지 확인하는 가장 쉬운 방법 (0) | 2020.11.07 |
리베이스 후 변경 사항이 손실 되었습니까? (0) | 2020.11.07 |
바이트 벡터 (u8)를 문자열로 어떻게 변환합니까? (0) | 2020.11.07 |