Эти загадочные True, False и Nil объекты Ruby
мая 4, 2010 | Published in Ruby, Основы
Каждое выражение и каждый объект в Ruby имеет булево значение, что означает, что каждый объект и каждое выражение оцениваются как true или как false. Это делает true и false довольно специфическими значениями в языке Ruby. При всем при этом, true и false являются не просто значениями, а объектами Ruby.
Объекты True и False
Вы, наверняка, знаете, что true и false — это зарезервированные слова Ruby, что означает, что вы не сможете использовать их как имена для переменных или методов. Но помимо этого, оба true и false также являются абсолютно полноценными объектами. Ruby имеет 2 специальных класса от которых происходят эти объекты, а именно:
TrueClass
и
FalseClass
и оба объекта true и false являются единственными экземплярами этих классов. Ruby не позволит вам создать несколько экземпляров этих классов, вы можете убедиться в этом посмотрев пример:
irb(main):001:0> true.class
=> TrueClass
irb(main):002:0> false.class
=> FalseClass
irb(main):003:0> p = TrueClass.new
NoMethodError: undefined method `new’ for TrueClass:Class
from (irb):3
irb(main):004:0> q = FalseClass.new
NoMethodError: undefined method `new’ for FalseClass:Class
from (irb):4
irb(main):005:0>
Но, как же каждое выражение в Ruby оценивается значением true или false? Хороший вопрос, постараюсь на него ответить. Каждое выражение в Ruby оценивается объектом и каждый объект в свою очередь может использоваться в условном выражении, что значит, что каждый объект в конечном счете должен оцениваться булевым значением. Вы можете убедиться в этом, взглянув на пример:
irb(main):001:0> if :hello
irb(main):002:1> puts ‘булево значение строкового или символьного объекта оценивается как true ‘
irb(main):003:1> end
булево значение строкового или символьного объекта оценивается как true
irb(main):004:0>
irb(main):005:0* if 5
irb(main):006:1> puts ‘булево значение целочисленного объекта также оценивается как true’
irb(main):007:1> end
булево значение целочисленного объекта также оценивается как true
irb(main):008:0>
irb(main):009:0* if !false
irb(main):010:1> puts ‘булево значение false будет false’
irb(main):011:1> end
булево значение false будет false
irb(main):012:0>
irb(main):013:0* if nil
irb(main):014:1> puts ‘nil не может быть true’
irb(main):015:1> else
irb(main):016:1* puts ‘булево значение nil — это false’
irb(main):017:1> end
булево значение nil — это false
irb(main):018:0>
irb(main):019:0*unless def method; end
irb(main):022:1* puts ‘объявление метода оценивается как false’
irb(main):023:1> end
объявление метода оценивается как false
irb(main):024:0>
Попробуйте это сами с любым выражением или объектом Ruby. Также можно убедиться в том, что значения true и false являются одними и теми же объектами (мы получаем тот же экземпляр TrueСlass или FalseClass), для этого нам необходимо лишь узнать каким id обладает тот или иной объект. Вы наверняка заметите, что для объектов true в равной степени, как и для объектов false, id будет всегда одинаковым. Более того, id объекта false всегда будет равен 0, а id объекта true всегда будет равен 2, например:
irb(main):001:0> true.object_id
=> 2
irb(main):002:0> false.object_id
=> 0
irb(main):003:0>
Таким образом, теперь мы знаем, что: каждое выражение в Ruby оценивается объектом, и каждый объект имеет булево значение. Булевы значения это всегда копии класса TrueClass или FalseClass и благодаря этому имеют всегда один и тот же id объекта. Многие объекты в Ruby будут иметь булево значение true, и только два объекта имеют булево значение false, это собственно объект false и объект nil.
Объект Nil
Объект nil – еще одна особенность Ruby. Nil — такой же объект, как и любой другой. Объект nil является экземпляром особого класса — NilClass. Я выше уже упоминал о том, что nil это один из двух объектов в Ruby, которые обладают булевым значением false.
Так же как true и false, у всех объектов nil id будет одинаковым. Id объекта nil всегда равен 4:
irb(main):001:0> nil.class
=> NilClass
irb(main):002:0> nil.object_id
=> 4
Самое интересное, что с помощью объекта nil в Ruby можно частично реализовать паттерн Null Object прибегая к минимальным усилиям. Объект nil уже снабжен некоторыми методами для того, чтобы вы могли его использовать при этом не получая надоедливых сообщений об ошибках в случаях, когда выполнение определенного фрагмента кода в результате возвратит nil. Именно поэтому объект nil ассоциируется и преобразуется в пустую строку, пустой массив, хэш или число 0. Пример:
irb(main):002:0> nil.to_s
=> «»
irb(main):003:0> nil.to_i
=> 0
irb(main):004:0> nil.to_a
=> []
Из-за того, что вы можете всегда добавлять методы к экземплярам классов в Ruby, а объект nil всегда является единственным экземпляром, вы можете добавить к объекту nil интересные методы, так что ваш код будет использовать nil в качестве Null Object, т.е.:
irb(main):001:0> def nil.quack
irb(main):002:1> puts ‘Кря, кря, кря не можешь сделать из меня паштет ведь я nil’
irb(main):003:1> end
irb(main):004:0> nil.quack
Кря, кря, кря не можешь сделать из меня паштет ведь я nil
irb(main):005:0>
Сейчас если исполняется код с объектами, которые умею крякать как утки и работа происходит с объектом nil вместо объекта DuckLike, то в этом случае ваш модернизированный объект nil сможет крякнуть что-то разумное о причине неработоспособности объекта DuckLike (или вывести ошибку, если это предпочтительно).
Я думаю это довольно мощный материал. Паттерн NullObject уже как бы встроен в язык, вам только необходимо использовать его в своих целях.
Перевод статьи