Доступ к переменной экземпляра в методе initialize - PullRequest
1 голос
/ 16 апреля 2019

Учитывая этот базовый класс в Ruby:

class TestClass
  def initialize(name)
    @name = name
  end
end

Как я могу получить доступ к имени переменной экземпляра напрямую из метода initialize без создания функции-получателя?это вообще возможно?(т. е. с использованием точечной нотации) или метод initialize перестает существовать после создания экземпляра класса, следовательно, необходимо определить метод получения?

Я думаю, что я пытаюсь спросить: initializeметод класса или экземпляра?

Ответы [ 2 ]

2 голосов
/ 16 апреля 2019

Да, есть способ.Но это не традиционный.Это больше похоже на запрос объекта на

TestClass.new("foo").instance_variable_get(:@name)
=> "foo"

Метод initialize не "перестает существовать".Это выполнено, вот и все.То, что ваш метод делает, в вашем случае, это то, что переменная установлена.

1 голос
/ 16 апреля 2019

«Метод получения» определен так, что вы можете использовать переменную вне класса:

class TestClass
  attr_reader :name

  def initialize(name)
    @name = name
  end
end
# TestClass.new('Ben').name  # => 'Ben'

Если вам не нужен доступ извне класса, вы можете просто использовать @name:

class TestClass
  def initialize(name)
    @name = name
  end

  def greet
    puts "Hello, %s" % @name
  end
end
# TestClass.new('Ben').greet # outputs: Hello, Ben

Вы можете использовать @name внутри инициализации:

class TestClass
  def initialize(name)
    @name = name
    puts "Name backwards: %s" % @name.reverse
  end
end
# TestClass.new('Ben') # outputs neB

Initialize - это специальный метод, когда вы определяете initialize метод экземпляра, он автоматически помечается private. Метод класса new вызывает его после создания экземпляра вашего класса.

Ничто не мешает вам вызывать закрытые методы внутри класса:

class TestClass
  def initialize(name)
    @name = name
    puts "Name is now %s" % @name
  end

  def flip_name
    initialize(@name.reverse)
  end
end
# t = TestClass.new('Ben') # outputs "Name is now Ben"
# t.flip_name # outputs "Name is now neB"
# t.instance_variable_get(:@name) # => 'neB'

Метод flip_name, который вызывает initialize, прекрасно работает, но, конечно, он довольно нетрадиционен и почти никогда не используется, потому что не имеет особого смысла.

Можно вызывать закрытые методы извне класса, используя send:

# t.send(:initialize, 'Bill') # outputs "Name is now Bill"
# t.instance_variable_get(:@name) # => 'Bill'

Без отправки вы получаете NoMethodError:

> t.initialize('Jack')
NoMethodError: private method `initialize' called for #<TestClass:0x00007fa2df8e4570>

Бета-версии Ruby 1.9 изменены на send и теперь действуют так же, как public_send, предоставляя доступ только к публичным методам, и будет funccall для вызова приватных методов, если вы действительно этого хотите, для целей модульного тестирования для пример. Я думаю, что это вызвало слишком много проблем с совместимостью, и изменение было отменено.

Итак, в заключение, да, вы можете снова вызвать initialize, и он не перестанет существовать, но это почти никогда не делается, потому что это имеет очень мало смысла. Чтобы получить доступ к переменным экземпляра изнутри класса, вы используете нотацию @, например @name, для доступа к ним из-за пределов класса вы определяете метод получения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...