Ruby - вызов другого метода класса в суперклассе - PullRequest
1 голос
/ 25 апреля 2011
class A
  def self.a
    puts "self: #{self}; superclass: #{superclass}"
  end
end

class B < A
  class << self; undef_method(:a); end  # I'm not allowed to use B.a
  def self.b
    # here I want to call A.a with B as self.
  end
end  

A.a  #=> self: A; superclass: Object
B.b  #=> self: B; superclass: A (expected)

Я не хочу alias_method решения. Я ищу что-то вроде это .

UPDATE

Решение не должно быть похоже на ссылку выше; это всего лишь предложение. Например, я пытался сделать:

class B < A
  def self.b
    instance_eval(&A.method(:a).to_proc)
  end
end

но так получается странный ArgumentError на Ruby 1.8.7.

Ответы [ 3 ]

2 голосов
/ 25 апреля 2011

При вызове метода в производном классе B относительно экземпляров производного класса нет абсолютно никакой разницы между объектом экземпляра A и объектом экземпляра B. Это один и тот же объект.

Таким образом, при рассмотрении методов экземпляра существует только один единственный объект. Концептуально возможно, если немного сложнее, как вы заметили, вызвать метод, определенный в родительском классе, но, конечно, с производным классом в качестве экземпляра self. Невозможно провести различие между объектом «A» и объектом «B», есть только один экземпляр, и они являются «одинаковыми» для A и B. Но для методов класса параллель с методом экземпляра отскок вы упомянутого просто не существует.

Теперь вы говорите о методах класса. Для методов класса, как вы знаете, self является классом. Экземпляры не имеют смысла. Вы не можете вызывать метод класса A. независимо от , не имея класса A или его метакласса self .

Другими словами, причина, по которой ваш упомянутый трюк работает, заключается в том, что существует только один объект, а для производного экземпляра он назван из производного класса. Невозможно сделать обратное без создания второго экземпляра недопустимого родительского класса. Но теперь, когда мы вызываем методы класса, они ... ну ... методы класса, поэтому нет никакой надежды на ссылку на производный класс. Как именно можно определить, что вы хотите?

2 голосов
/ 25 апреля 2011

Я не думаю, что это возможно с использованием подхода SuperProxy, с которым вы связаны.

В этом случае A.method(:a) - это одноэлементный метод.Одноэлементные методы могут быть связаны только с объектом, с которым он был создан.В частности, он не может быть восстановлен до B.

Вот первый нерабочий подход, который я попробовал:

class B < A
  def self.b
    A.method(:a).unbind.bind(self).call
  end
end

Второй нерабочий подход:

class B < A
  class << self
    define_method :b, A.method(:a)
  end
end

Оба генерируют исключение «TypeError: метод singleton, связанный с другим объектом».

1 голос
/ 18 августа 2011

Единственным решением здесь является использование B.a.

class B < A
  def self.b
    a #=> self: B; superclass: A
  end
end  
...