Чтение онлайн

ЖАНРЫ

Программирование на языке Ruby
Шрифт:

require 'pathname'

path = Pathname.new("/tmp/myfile")

name = path.to_s # "/tmp/myfile"

name = path.to_str # "/tmp/myfile" (Ну и что?)

# Вот где это оказывается полезно...

heading = "Имя файла равно " + path

puts heading# " Имя файла равно /tmp/myfile"

В этом фрагменте мы просто дописали путь в конец обычной строки

"Имя файла равно"
. Обычно такая операция приводит к ошибке во время выполнения, поскольку оператор
+
ожидает,
что второй операнд — тоже строка. Но так как в классе
Pathname
есть метод
to_str
, то он вызывается. Класс
Pathname
«маскируется» под строку, то есть может быть неявно преобразован в
String
.

На практике методы

to_s
и
to_str
обычно возвращают одно и то же значение, но это необязательно. Неявное преобразование должно давать «истинное строковое значение» объекта, а явное можно расценивать как «принудительное» преобразование.

Метод

puts
обращается к методу
to_s
объекта, чтобы получить его строковое представление. Можно считать, что это неявный вызов явного преобразования. То же самое справедливо в отношении интерполяции строк. Вот пример:

class Helium

 def to_s

"He"

 end

 def to_str

"гелий"

 end

end

e = Helium.new

print "Элемент "

puts e # Элемент He.

puts "Элемент " + e # Элемент гелий.

puts "Элемент #{e}" # Элемент He.

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

Предположим, например, что вы написали метод, который ожидает в качестве параметра объект

String
. Вопреки философии «утипизации», так делают часто, и это вполне оправдано. Например, предполагается, что первый параметр метода
File.new
— строка.

Решить эту проблему просто. Если вы ожидаете на входе строку, проверьте, имеет ли объект метод

to_str
, и при необходимости вызывайте его.

def set_title(title)

 if title.respond_to? :to_str

title = title.to_str

 end

 # ...

end

Ну а если объект не отвечает на вызов метода

to_str
? Есть несколько вариантов действий. Можно принудительно вызвать метод
to_s
; можно проверить, принадлежит ли объект классу
String
или его подклассу; можно, наконец, продолжать работать, понимая, что при попытке выполнить операцию, которую объект не поддерживает, мы получим исключение
ArgumentError
.

Короткий путь к цели выглядит так:

title = title.to_str rescue title

Он опирается на тот факт, что при отсутствии реализации метода

to_str
возникнет исключение. Разумеется, модификаторы
rescue
могут быть вложенными:

title = title.to_str rescue title.to_s rescue title

# Обрабатывается маловероятный
случай, когда отсутствует даже метод to_s.

С помощью неявного преобразования можно было бы сделать строки и числа практически эквивалентными:

class Fixnum

 def to_str

self.to_s end

 end

str = "Число равно " + 345 # Число равно 345.

Но я не рекомендую так поступать: «много хорошо тоже нехорошо». В Ruby, как и в большинстве языков, строки и числа — разные сущности. Мне кажется, что ясности ради преобразования, как правило, должны быть явными.

И еще: в методе

to_str
нет ничего волшебного. Предполагается, что он возвращает строку, но если вы пишете такой метод сами, ответственность за то, что он действительно так и поступает, ложится на вас.

2.17. Дописывание в конец строки

Для конкатенации строк применяется оператор

<<
. Он «каскадный», то есть позволяет выполнять подряд несколько операций над одним и тем же операндом-приемником.

str = "А"

str << [1,2,3].to_s << " " << (3.14).to_s

# str теперь равно "А123 3.14".

Если число типа

Fixnum
принадлежит диапазону 0..255, то оно будет преобразовано в символ:

str = "Marlow"

str << 101 << ", Christopher"

# str теперь равно "Marlowe, Christopher".

2.18. Удаление хвостовых символов новой строки и прочих

Часто бывает необходимо удалить лишние символы в конце строки. Типичный пример — удаление символа новой строки после чтения строки из внешнего источника.

Метод

chop
удаляет последний символ строки (обычно это символ новой строки). Если перед символом новой строки находится символ перевода каретки (
\r
), он тоже удаляется. Причина такого поведения заключается в том, что разные операционные системы неодинаково трактуют понятие «новой строки». В UNIX-подобных системах новая строка представляется символом
\n
. А в DOS и Windows для этой цели используется пара символов
\r\n
.

str = gets.chop # Прочитать, удалить символ новой строки.

s2 = "Some string\n" # "Some string" (нет символа новой строки).

s3 = s2.chop! # s2 теперь тоже равно "Some string".

s4 = "Other string\r\n"

s4.chop! # "Other string" (нет символа новой строки).

Обратите внимание, что при вызове варианта

chop!
операнд-источник модифицируется.

Важно еще отметить, что последний символ удаляется, даже если это не символ новой строки:

str = "abcxyz"

s1 = str.chop # "abcxy"

Поскольку символ новой строки присутствует не всегда, иногда удобнее применять метод

chomp
:

str = "abcxyz"

str2 = "123\n"

str3 = "123\r"

str4 = "123\r\n"

s1 = str.chomp # "abcxyz"

s2 = str2.chomp # "123"

# Если установлен стандартный разделитель записей, то удаляется не только

Поделиться с друзьями: