Когда вы используете attr_accessor :venue
, вы по сути делаете это.
def venue
@venue
end
def venue=(value)
@venue = value
end
Когда вы делаете attr_writer :venue
, вы делаете
def venue=(val)
@venue = val
end
Когда вы делаете attr_reader :venue
, вы делаете
def venue
@venue
end
Обратите внимание, что @instance_variable
по умолчанию nil
или если он неинициализирован.Чтобы увидеть это в действии, введите irb
в своем терминале и нажмите ввод.Затем введите один @
и спамите кучу символов после него.@ausdhyf934234092348
будет ноль.
Когда вы находитесь внутри Ticket#initialize
, вы действуете как экземпляр объекта, поэтому self
вернет текущий экземпляр.self.class
вернет класс и предоставит вам доступ к любым методам уровня класса.
class Ticket
VENUE_SIZES = [:small, :large]
def self.venue_sizes
VENUE_SIZES
end
def initialize(venue, date)
# ...
self.venue_sizes # NoMethodError
self.class.venue_sizes # [:small, :large]
end
end
Поднимаясь по цепочке, если вы действуете как класс, а не как экземпляр класса, вызываяself.class
- или self.class.class
, если вы действуете как экземпляр, вернет Class
attr_accessor
- просто синтаксический сахар;это было сделано из-за рутинной рутины того, что нужно снова и снова писать эти методы получения / установки.Есть более сложные проблемы, такие как написание нашего nadnerb_accessor
на Ruby (хотя attr_accessor
реализован на C):
class Ticket
def self.nadnerb_accessor(*names)
names.each do |name|
define_method(name) do
instance_variable_get(:"@#{name}")
end
define_method("#{name}=") do |value|
instance_variable_set(:"@#{name}", value)
end
end
end
nadnerb_accessor :venue, :price
def initialize(venue, price)
self.venue = venue
self.price = price
end
def inspect
"#<Ticket @venue=\"#{@venue}\" @price=\"#{@price}\">"
end
end
ticket = Ticket.new("StackOverflow", "$5")
puts ticket.inspect