Перемешивание attr_accessor и метод инициализации в одном классе
Я вижу код вроде:
class Person
def initialize(name)
@name = name
end
end
Я понимаю, это позволяет мне делать такие вещи, как person = Person.new
, и использовать @name
в другом месте моего класса, как и другие методы. Затем я увидел код вроде:
class Person
attr_accessor :name
end
...
person = Person.new
person.name = "David"
Я просто в недоумении с этими двумя методами mesh. Каковы особенности использования def initialize(name)
? Я полагаю, что attr_accessor
позволяет мне читать и писать. Это означает, что это два отдельных метода. Да? Хотите уточнения на def initialize
и attr_accessor
и как они мешают.
Ответы
Ответ 1
initialize
и attr_accessor
не имеют ничего общего друг с другом. attr_accessor :name
создает несколько методов:
def name
@name
end
def name=(val)
@name = val
end
Если вы хотите установить имя при создании объекта, вы можете сделать это в инициализаторе:
def initialize(name)
@name = name
# or
# self.name = name
end
Но вам не обязательно это делать. Вы можете установить имя позже, после создания.
p = Person.new
p.name = "David"
puts p.name # >> "David"
Ответ 2
Вот ответ, который вы ищете Classes and methods
. Прочтите внимательно.
Вот хорошая документация по ссылке:
Классы и методы
Теперь мы готовы создать наш собственный класс адресов. Пусть начнется просто. Начните с адреса, который содержит только поле "улица".
Вот как вы определяете класс:
class Address
def initialize(street)
@street = street
end
end
Пропустите это:
-
Ключевое слово класса определяет класс.
-
Определяя метод внутри этого класса, мы связываем его с этим классом.
-
Метод инициализации - это то, что фактически создает структуру данных. Каждый класс должен содержать метод инициализации.
@street - это переменная объекта. Подобно клавишам хеша. Знак @отличает @street как объектную переменную. Каждый раз, когда вы создаете объект класса Address, этот объект будет содержать переменную @street.
Используйте этот класс для создания адресного объекта.
address = Addres.new("23 St George St.")
Что это. адрес теперь является объектом класса Address
Чтение данных в объекте
Предположим, что мы хотим прочитать данные в адресном объекте. Для этого нам нужно написать метод, который возвращает эти данные:
class Address
def initialize(street)
@street = street
end
# Just return @street
def street
@street
end
end
Теперь метод Address # street позволяет вам прочитать улицу адреса. В irb:
>> address.street
=> "23 St George St."
Свойство объекта, которое видимо снаружи, называется атрибутом. В этом случае улица является атрибутом. В частности, это читаемый атрибут. Поскольку этот тип атрибута очень распространен, Ruby предлагает вам ярлык через ключевое слово attr_reader:
class Address
attr_reader :street
def initialize(street)
@street = street
end
end
Изменение данных в объекте
Мы также можем определить метод изменения данных в объекте.
class Address
attr_reader :street
def initialize(street)
@street = street
end
def street=(street)
@street = street
end
end
Ruby довольно умен в использовании метода street =
`address.street = "45 Main St`."
Обратите внимание, что вы можете поместить пробелы в betten street и =. Теперь, когда мы можем изменить адресные данные, мы можем упростить метод initialize, и просто по умолчанию для улицы нужно удалить пустую строку "".
class Address
attr_reader :street
def initialize
@street = ""
end
def street=(street)
@street = street
end
end
address = Address.new
address.street = "23 St George St."
Это может показаться немного упрощенным, но когда мы добавим поля города, штата и zip, а также другие методы, это упростит определение класса.
Теперь улица также является атрибутом, доступным для записи. Как и прежде, вы можете объявить его как таковой с attr_writer:
class Address
attr_reader :street
attr_writer :street
def initialize
@street = ""
end
end
Доступ к данным
Очень часто у вас есть атрибуты, которые являются читаемыми и записываемыми атрибутами. Ruby позволяет объединить их вместе с attr_accessor. Я предполагаю, что они будут называться "доступными атрибутами", но я никогда не видел, чтобы их называли такими.
class Address
attr_accessor :street
def initialize
@street = ""
end
end
Благодаря этим знаниям теперь легко определить всю структуру адресной книги. Как выясняется, attr_accessor и друзья принимают несколько аргументов.
class Address
attr_accessor :street, :city, :state, :zip
def initialize
@street = @city = @state = @zip = ""
end
end
Ответ 3
Я думаю, что вы рассматриваете initialize
как конструктор. Если быть точным, это не так. Конструктор по умолчанию - это метод new
в классе, и этот метод вызывается initialize
. Если вы не определяете initialize
, вы все равно можете создать объект с new
, потому что initialize
не является самим конструктором. В этом случае значение по умолчанию initialize
ничего не делает. Если вы определяете initialize
, то это вызывается сразу после создания объекта.
Утверждение @foo = ...
и attr_accessor :foo
различны. Первый присваивает значение переменной экземпляра @foo
, тогда как последняя позволяет вам получить доступ к @foo
с помощью методов foo
и foo=
. Без последнего вы можете получить доступ к @foo
, просто описав это.
Ответ 4
В отличие от С++ переменные экземпляра Java в Ruby по умолчанию являются частными (частично, поскольку они могут быть доступны с помощью a.instance_variable_get: @x)
например:
class Dda
def initialize task
@task = task
@done = false
end
end
item = Dda.new "Jogging" # This would call the initializer and task = Jogging would
be set for item
item.task # would give error as their is no function named task to access the instance
variable.
Хотя мы установили значение для элемента, но мы не сможем что-либо с ним сделать, поскольку переменные instace являются частными в ruby.
код для getter:
def task
@task
end
#for getter
def task=task
@task = task
end
Использование getter гарантирует, что item.task вернет значение
И использование setter дает нам гибкость для предоставления значений переменным экземпляра в любое время.