Переопределение одноэлементного метода родителя

В C# обычный класс не может наследовать от статического класса. Аналогичный случай для Ruby выглядит следующим образом:

class Foo
  class << self
    def test
      "this is test"
    end
  end
end

class Bar < Foo
  def test
    puts super
  end
end

Bar.new.test # >> error

Есть ли способ, чтобы обычный класс Bar наследовал от Foo и переопределял test?


person Community    schedule 06.03.2019    source источник
comment
В рубине нет статических классов. Это наследование здесь работает просто отлично. Bar#test не может найти суперметод, потому что его нет. test то есть в Foo живет на другом уровне. Не экземпляры класса, а сам объект класса. В общем, непонятно, что вы пытаетесь здесь спросить.   -  person Sergio Tulentsev    schedule 06.03.2019
comment
@SergioTulentsev Есть ли способ позвонить super, чтобы было напечатано "this is test"?   -  person    schedule 06.03.2019
comment
Да, определите test в Bar так же, как метод singleton. Это сделало бы Foo.test его правильным суперметодом.   -  person Sergio Tulentsev    schedule 06.03.2019
comment
Нет ничего плохого в том, как вы определили Foo::test (значение :: означает, что это метод класса, в отличие от Foo#test, если бы это был метод экземпляра), но нормальный (сокращенный) способ написания — def self.test; ... ; end (что здесь то же самое как def Foo.test; ... ; end).   -  person Cary Swoveland    schedule 06.03.2019


Ответы (1)


Есть ли способ для Bar унаследовать от Foo

Вы сделали эту часть правильно

и переопределить test?

Вам нужно определить Bar.test как метод класса, но то, что вы написали, является определением метода экземпляра (и вызовом). Пытаться

class Bar < Foo
  class << self
    def test
      super + ", man"
    end
  end
end

Bar.test
#=> "this is a test, man"

В Ruby нет такого понятия, как статический класс или метод, поэтому вызов метода экземпляра Bar.new.test никогда не будет ссылаться на то же самое, что и вызов метода класса Bar.test, как это может быть в языках с концепцией статических методов.

person Andrew Schwartz    schedule 06.03.2019
comment
Значит, единственный способ заставить его работать — это сделать метод test внутри Bar синглтона? - person ; 06.03.2019
comment
Да, иначе вы ничего не переопределяете. Другой способ увидеть это: Foo.new.test не вызовет ваш метод, определенный в классе Foo. (Совет: не используйте имя test, так как это метод для Kernel, поэтому сообщения об ошибках могут быть более запутанными, чем должны быть.) - person Andrew Schwartz; 07.03.2019