Programing

클래스가 정의되었는지 어떻게 확인합니까?

lottogame 2020. 11. 4. 07:35
반응형

클래스가 정의되었는지 어떻게 확인합니까?


문자열을 클래스 이름으로 바꾸는 방법은 해당 클래스가 이미있는 경우에만 가능합니까?

Amber가 이미 클래스 인 경우 다음을 통해 문자열에서 클래스로 이동할 수 있습니다.

Object.const_get("Amber")

또는 (Rails에서)

"Amber".constantize

그러나 NameError: uninitialized constant AmberAmber가 아직 클래스가 아닌 경우 이들 중 하나가 실패 합니다.

내 첫 번째 생각은 defined?방법 을 사용하는 것이지만 이미 존재하는 클래스와 그렇지 않은 클래스를 구별하지 않습니다.

>> defined?("Object".constantize)
=> "method"
>> defined?("AClassNameThatCouldNotPossiblyExist".constantize)
=> "method"

그렇다면 변환을 시도하기 전에 문자열이 클래스 이름을 지정하는지 어떻게 테스트합니까? (좋아요, NameError 오류를 잡는 begin/ rescue블록은 어떻습니까? 너무 못 생겼나요? 동의합니다 ...)


어때요 const_defined??

Rails에서는 개발 모드에서 자동 로딩이 있으므로 테스트 할 때 까다로울 수 있습니다.

>> Object.const_defined?('Account')
=> false
>> Account
=> Account(id: integer, username: string, google_api_key: string, created_at: datetime, updated_at: datetime, is_active: boolean, randomize_search_results: boolean, contact_url: string, hide_featured_results: boolean, paginate_search_results: boolean)
>> Object.const_defined?('Account')
=> true

레일에서는 정말 쉽습니다.

amber = "Amber".constantize rescue nil
if amber # nil result in false
    # your code here
end

위의 @ctcherry의 응답에서 영감을 얻은 여기 class_name에 문자열이있는 '안전한 클래스 메서드 전송' 이 있습니다. 경우 class_name클래스의 이름이없는, 그것은 nil을 반환합니다.

def class_send(class_name, method, *args)
  Object.const_defined?(class_name) ? Object.const_get(class_name).send(method, *args) : nil
end

응답하는 method경우에만 호출하는 더 안전한 버전 class_name:

def class_send(class_name, method, *args)
  return nil unless Object.const_defined?(class_name)
  c = Object.const_get(class_name)
  c.respond_to?(method) ? c.send(method, *args) : nil
end

Object.const_defined?방법을 사용한 모든 답변 에는 결함이있는 것으로 보입니다 . 지연로드로 인해 해당 클래스가 아직로드되지 않은 경우 어설 션이 실패합니다. 이것을 확실하게 달성하는 유일한 방법은 다음과 같습니다.

  validate :adapter_exists

  def adapter_exists
    # cannot use const_defined because of lazy loading it seems
    Object.const_get("Irs::#{adapter_name}")
  rescue NameError => e
    errors.add(:adapter_name, 'does not have an IrsAdapter')
  end

문자열이 유효한 클래스 이름 (또는 쉼표로 구분 된 유효한 클래스 이름 목록)인지 테스트하기 위해 유효성 검사기를 만들었습니다.

class ClassValidator < ActiveModel::EachValidator
  def validate_each(record,attribute,value)
    unless value.split(',').map { |s| s.strip.constantize.is_a?(Class) rescue false }.all?
      record.errors.add attribute, 'must be a valid Ruby class name (comma-separated list allowed)'
    end
  end
end

수업을 받고 싶은 경우를 대비 한 또 다른 접근 방식입니다. 클래스가 정의되지 않은 경우 nil을 반환하므로 예외를 포착 할 필요가 없습니다.

class String
  def to_class(class_name)
    begin
      class_name = class_name.classify (optional bonus feature if using Rails)
      Object.const_get(class_name)
    rescue
      # swallow as we want to return nil
    end
  end
end

> 'Article'.to_class
class Article

> 'NoSuchThing'.to_class
nil

# use it to check if defined
> puts 'Hello yes this is class' if 'Article'.to_class
Hello yes this is class

참고URL : https://stackoverflow.com/questions/5758464/how-do-i-check-if-a-class-is-defined

반응형