В классе Ruby, который наследуется от String, как получить "# {my_string}" с явным .to_s - PullRequest
1 голос
/ 24 марта 2012

Короче говоря, я ожидаю, что все три # {} в последней строке этой тестовой программы приведут к одной и той же строке, а они - нет. Это работает, если мой класс наследует от Object.

> ./test.rb 
A string foobar, and MyString: , MyString.to_s: foobar

> cat test.rb 

    #!/usr/bin/env ruby

    class MyString < String
      def initialize s
        @s= s.to_s
        @simple = s.index(?+)
      end
      def to_s() @s end
    end

x='foobar'

puts "A string #{x}, and MyString: #{
        MyString.new(x)}, MyString.to_s: #{MyString.new(x).to_s}"

Ответы [ 2 ]

3 голосов
/ 24 марта 2012

Кажется, что строковая интерполяция обрабатывает объекты типа String по-разному:

irb(main):011:0> class MyString < String
irb(main):012:1>   def initialize(str)
irb(main):013:2>     @str = str
irb(main):014:2>   end
irb(main):015:1>   def to_s
irb(main):016:2>     puts "to_s called!"
irb(main):017:2>     @str
irb(main):018:2>   end
irb(main):019:1> end
=> nil
irb(main):020:0> "#{MyString.new('foo')}"
=> ""

Как видите, to_s даже не вызывается.Причиной этого является инвариант str.to_s == str, где str.is_a? String.Вы нарушили этот инвариант, запутав тем самым код библиотеки.

Заключение : не переопределяйте to_s, если вы используете подкласс String (в любом случае это не имеет большого смысла).

2 голосов
/ 24 марта 2012

Поскольку Niklas B. демонстрирует , интерполяция строки не вызывает to_s для String объектов. Значением по умолчанию для аргумента String#initialize является "", поэтому все экземпляры вашего подкласса фактически являются пустыми строками.

Один из способов заставить это работать - вызвать super в методе initialize, если ваш подкласс, и передать строковое значение:

class MyString < String
  def initialize s
    super s.to_s    # this line added
    @s= s.to_s
    @simple = s.index(?+)
  end
  def to_s() @s end
end

puts "#{MyString.new("foo")}"  # => produces "foo"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...