Что такое аксессор?
Мы кратко обсудили @-переменные в предшествующих главах, но мало поэкспериментировали с ними. @-переменные объекта являются его атрибутами, тем, что обычно отличает его от других объектов этого же класса. Важно иметь возможность задавать и считывать значения атрибутов; для этого необходимо написание методов, называемых аксессорами атрибутов . Через мгновение мы увидим, что не всегда нужно явное задание аксессоров, но давайте сейчас полностью пройдем по этому пути. Есть два вида аксессоров - writers и readers .
ruby> **class Fruit** |**def set_kind(k) # a writer** |**@kind = k** |**end** |**def get_kind # a reader** |**@kind** |**end** | **end** **nil** ruby> **f1 = Fruit.new** **#<Fruit:0xfd7e7c8c>** ruby> **f1.set_kind("peach") # use the writer** **"peach"** ruby> **f1.get_kind # use the reader** **"peach"** ruby> f1 # inspect the object **#<Fruit:0xfd7e7c8c @kind="peach">**
Достаточно просто; мы можем сохранять и считывать информацию о том, на фрукт какого вида мы смотрим. Но имена наших методов слегка многословны. Пример далее имеет более ясный и привычный вид:
ruby> **class Fruit** |**def kind=(k)** |**@kind = k** |**end** |**def kind** |**@kind** |**end** | **end** **nil** ruby> **f2 = Fruit.new** **#<Fruit:0xfd7e7c8c>** ruby> **f2.kind = "banana"** **"banana"** ruby> **f2.kind** **"banana"**
Метод
inspect
Краткое отступление. Вы уже заметили, что когда мы прямо рассматриваем объект, нам показывают нечто загадочное, типа
#<anObject:0x83678>. Это просто действие по умолчанию, и мы свободно можем изменить его. Все, что нужно сделать - это добавить метод
inspectв определение класса. Он должен возвращать строковое значение, описывающее объект подходящим способом, включая состояние всех или некоторых @-переменные.
ruby> **class Fruit** |**def inspect** |**"a fruit of the " + @kind + " variety"** |**end** | **end** **nil** ruby> **f2** **"a fruit of the banana variety"**
Ему соответствует метод
to_s(перевести в строку), который используется для вывода на печать объекта. В общем случае, можно представлять себе
inspectкак средство, используемое при написании и отладке программ, а
to_sкак способ обогащения вывоа программы.
eval.rbиспользует
inspectдля вывода результатов. Вы можете использовать метод
pдля выполнения простого вывода при отладке программы.
# Эти две строки эквивалентны: p anObject print anObject.inspect, "\n"
Легкий способ создания аксессоров
Поскольку многие @-переменные нуждаются в применении аксессоров, Ruby предоставляет удобные сокращения для стандартных форм.
|
Сокращение
|
Эффект (значение)
|
|
attr_reader :v|
def v; @v; end|
|
attr_writer :v|
def v=(value); @v=value; end|
|
attr_accessor :v|
attr_reader :v; attr_writer :v|
|
attr_accessor :v, :w|
attr_accessor :v; attr_accessor :w|
Давайте воспользуемся этими преимуществами и добавим в пример информацию о свежести. Сперва мы затребуем автоматическую генерацию reader-а и writer-а, а затем включим новую информацию в
inspect:
ruby> **class Fruit** |**attr_accessor :condition** |**def inspect** |**"a " + @condition + @kind"** |**end** | **end** **nil** ruby> **f2.condition = "ripe"** **"ripe"** ruby> **f2** **"a ripe banana"**
More fun with fruit
Никто не ест гнилые фрукты - так пусть время делает свое черное дело.
ruby> **class Fruit** |**def time_passes** |**@condition = "rotting"** |**end** | **end** **nil** ruby> **f2** **"a ripe banana"** ruby> **f2.time_passes** **"rotting"** ruby> **f2** **"a rotting banana"**
Но играя с нашим классом, мы внесли некоторую проблему. Что будет, если мы попытаемся сейчас создать третий фрукт? Вспомните, @-переменные не существуют до тех пор, пока им не присваивается какое-либо значение.
ruby> **f3 = Fruit.new** **ERR: failed to convert nil into String**
Это метод
inspectжалуется здесь, и на то есть причина. Мы попросили его дать отчет о типе и состоянии фрукта, но до сих пор
f3не был присвоен не один атрибут. Если бы мы пожелали, то можно было бы переписать метод
inspectтаким образом, чтобы он проверял определенность @-переменных используя метод
defined?и давал по ним отчет только при положительном исходе, но, наверное, так будет не учень хорошо; т.к. каждый фрукт имеет вид и состояние, то желательно было бы каким-либо образом обеспечить их задание. Это и будет темой следующей главы.