Подтвердить что ты не робот

Перемешивание 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 и как они мешают.

4b9b3361

Ответ 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 дает нам гибкость для предоставления значений переменным экземпляра в любое время.