클래스 메소드에 alias_method가 있습니까?


10

다음 클래스를 고려하십시오.

class Foo
  def an_inst_method
    'instance method'
  end

  def self.a_class_method
    'class method'
  end

  alias_method :a_new_inst_method, :an_inst_method
end

이것은 문제가 아니며 문제없이 전화 할 수 있습니다 Foo.new.a_new_inst_method.

클래스와 같은 클래스 메소드를 사용 Foo.add_widget(*items)하고 별칭을 지정하여 다음과 같은 작업을 수행 할 수 있기를 바랍니다.

Foo.add_widget 'item1'
Foo.add_widgets 'item2', 'item3'

같은 본질적으로는 "루비 스타일"을 가지고 1.minute2.minutes나는 별명에 할 수 있도록 Foo.add_widget그렇게 전화 Foo.add_widgets통화를 동일한 방법. 나는 그것을 감쌀 수 있다는 것을 알고 있지만 더 깨끗한 방식으로 이것을 할 수 있어야한다고 생각합니다.

다음과 같은 시도를 해보십시오.

class Foo
  def an_inst_method
    'instance method'
  end

  def self.a_class_method
    'class method'
  end

  alias_method :a_new_inst_method, :an_inst_method
  alias_method :a_new_class_method, :a_class_method
end

그러나 다음과 같은 오류가 발생합니다.

NameError (undefined method `a_class_method' for class `Foo')

클래스 클래스에서는 작동하지 않는 것 같습니다. 이 작업은 어떻게합니까?

답변:


9

alias_method수신자의 인스턴스 메소드 별명. 클래스 메소드는 실제로 클래스싱글 톤 클래스 에 정의 된 인스턴스 메소드 입니다.

class MyClass
  def self.a
    "Hello World!"
  end
end

method_1 = MyClass.method(:a).unbind
method_2 = MyClass.singleton_class.instance_method(:a)

method_1 == method_2
#=> true

싱글 톤 클래스에 정의 된 인스턴스 메소드의 별명을 지정하려면 class << object구문 을 사용하여 열 수 있습니다 .

class << MyClass
  alias_method :b, :a
end

MyClass.b
#=> "Hello World!"

또는 singleton_class방법을 사용하여 직접 참조 할 수 있습니다 .

MyClass.singleton_class.alias_method :c, :a

MyClass.c
#=> "Hello World!"

당신이 여전히 클래스 컨텍스트 내에 있다면 클래스 self를 참조 할 것입니다. 위의 내용도 다음과 같이 쓸 수 있습니다.

class MyClass
  class << self
    def a
      "Hello World!"
    end
    alias_method :b, :a
  end
end

또는

class MyClass
  def self.a
    "Hello World!"
  end
  singleton_class.alias_method :c, :a
end

또는이 둘의 조합.


5

클래스 메소드와 해당 alias_method호출을 별도의 모듈로 랩핑 하고 다음을 통해 해당 모듈을 클래스에 통합 할 수 있습니다 extend.

class Foo
  def an_inst_method
    'instance method'
  end
  alias_method :a_new_inst_method, :an_inst_method

  module ClassMethods
    def a_class_method
      'class method'
    end
    alias_method :a_new_class_method, :a_class_method
  end

  extend ClassMethods
end

야! 나는 extend ClassMethods해결책을 잊었다 . +1
aarona

4

알아야 할 중요한 것은 Ruby 에는 클래스 메소드와 같은 것이 없다는 것 입니다.

클래스 메소드는 실제로 싱글 톤 메소드입니다. 클래스 메소드에는 특별한 것이 없습니다. 모든 객체 는 싱글 톤 메소드를 가질 수 있습니다. " Class인스턴스의 단일 메소드 Class"가 너무 길고 다루기 어렵 기 때문에 객체가 "클래스 메소드"라고 부릅니다 .

기다림! "단일 방법"이라고 했습니까?

이해해야 할 또 다른 중요한 사항 은 Ruby 에는 싱글 톤 방법과 같은 것이 없다는 것 입니다.

싱글 톤 메소드는 실제로 싱글턴 클래스의 일반적인 지루한 오래된 인스턴스 메소드입니다. 싱글 톤 방법에는 특별한 것이 없습니다. 그것들은 다른 인스턴스 메소드와 마찬가지로 인스턴스 메소드입니다.

실제로 Ruby에는 인스턴스 메소드 있습니다. 함수, 생성자, 정적 메서드, 클래스 메서드, 모듈 함수, 단일 메서드가 없습니다.

문제는 "이것은 클래스 메소드 입니까 , 단일 메소드 입니까?"가 아니라 " 이 메소드가 어떤 모듈 에 정의되어 있습니까?"입니다.

"Singleton 메서드"는 실제로 싱글턴 클래스에 정의 된 인스턴스 메서드입니다. 싱글 톤 클래스에 액세스하는 구문 foo은 다음과 같습니다.

class << foo
end

Object#singleton_class객체의 싱글 톤 클래스를 반환 하는 메소드도 있습니다 .

모든 메소드 가 인스턴스 메소드이고 클래스 메소드가 존재하지 않는다는 사실에 대해 왜 적극적으로 망치고 있습니까? Ruby의 객체 모델이 사람들이 생각하는 것보다 훨씬 단순하다는 것을 의미하기 때문입니다! 결국, 귀하의 질문에 이미 인스턴스 메소드의 별칭을 지정하는 방법을 알고 있지만 클래스 메소드의 별칭을 지정하는 방법을 모른다고 말합니다. 그러나 그것은 잘못입니다! 당신은 할 수 있기 때문에, 어떻게 별칭 클래스 메서드에 알고 그들은 단지 인스턴스 메소드입니다 . 이 사실을 올바르게 배웠다면이 질문을 할 필요가 없었을 것입니다!

모든 메소드가 인스턴스 메소드이고 "싱글 톤 메소드"라고하는 것이 싱글턴 클래스의 인스턴스 메소드라는 것을 이해하면 솔루션이 명확 해집니다.

singleton_class.alias_method :a_new_class_method, :a_class_method

참고 : 위에서 "X와 같은 것은 없다"고 썼을 때, " 루비 언어의 X와 같은 것은 없다"라는 뜻이었습니다 . 즉 않습니다 하지 그 개념이 존재하지 않는 것을 의미 루비 커뮤니티에서 .

우리는 정기적으로는 "싱글 톤 클래스의 인스턴스 메소드"또는 인스턴스 될 일이 객체의 싱글 톤 클래스의 "인스턴스 메서드에 대해 이야기보다 쉽습니다 간단하기 때문에,"싱글 방법 "과"클래스 메소드 "에 대해 이야기 Class클래스 ". 같은 경우에도 방법이 있습니다 Object#define_singleton_method, Object#singleton_method, Object#singleton_methods, Module#private_class_method, Module#public_class_method,과 Module#module_function의 루비 코어 라이브러리. 그러나 언어 개념 이 아니라는 점을 항상 기억해야합니다 . 그것들은 우리의 머리 와 일부 도서관 방법의 이름 에만 존재하는 공동체 개념입니다 .


2

좋아, 내가 이런 식으로 할 수있는 것처럼 보이고 작동합니다.

class Foo
  def an_inst_method
    'instance method'
  end

  def self.a_class_method
    'class method'
  end

  alias_method :a_new_inst_method, :an_inst_method

  class << self
    alias_method :a_new_class_method, :a_class_method
  end
end

Foo.a_class_method # => "class method" 
Foo.a_new_class_method # => "class method"

누구든지 여기에 루비 언어에 관한 유용한 정보가 있고 종합적인 답변을 제출하고 싶다면 +1을 줄 것입니다.


1
당신이 class << self뒤 따르면 alias_method :a_new_class_method, :a_class_method실제로 alias_method싱글 톤 클래스를 호출 합니다 Foo. 이것을 쓰는 또 다른 방법은 singleton_class.alias_method :a_new_class_method, :a_class_method클래스 컨텍스트입니다.
3limin4t0r

답에서 무엇을 더 원하십니까? 이것이 가장 깨끗한 해결책 일 것입니다.
데이브 뉴턴

@ 3limin4t0r 대답하면 +1하겠습니다. 이 추가 정보에 감사드립니다.
aarona

@DaveNewton 당신 말이 맞지만, 누군가가 문제를 간접적으로 해결하더라도 문제에 대해 더 의미있는 정보를 제공 할 수 있다면 철학도 보상해야한다고 생각합니다.
aarona

2

alias_method인스턴스에서 작동하므로 한 단계 더 깊이 이동하여 Class인스턴스 또는 클래스의 metaclass 에서 작동해야합니다 . 루비에는 일종의 두뇌 파괴가 될 수있는 야생의 객체 모델이 있지만, 또한 많은 힘을줍니다 :

class Foo
  def an_inst_method
    'instance method'
  end

  alias_method :a_new_inst_method, :an_inst_method

  class << self
    def a_class_method
      'class method'
    end

    alias_method :a_new_class_method, :a_class_method
  end
end

나는 레일스 컨텍스트에서 약 10 년 동안 루비를 사용해 왔지만 최근에야 객체 모델에 대해 심도있게 다이빙을 시작했습니다. 너무 멋진 것들이 있습니다!
aarona
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.