Что такое аксессор?
Мы кратко обсудили @-переменные в предшествующих главах, но мало поэкспериментировали с ними. @-переменные объекта являются его атрибутами, тем, что обычно отличает его от других объектов этого же класса. Важно иметь возможность задавать и считывать значения атрибутов; для этого необходимо написание методов, называемых аксессорами атрибутов . Через мгновение мы увидим, что не всегда нужно явное задание аксессоров, но давайте сейчас полностью пройдем по этому пути. Есть два вида аксессоров - 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
- 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?