Ruby 在“initialize”方法之外声明实例变量

Ruby 在“initialize”方法之外声明实例变量,ruby,initialization,instance-variables,Ruby,Initialization,Instance Variables,我被教导使用def initialize声明我的实例变量。我一直认为我只能在initialize方法中声明实例变量 尽管如此,我还是在我的initialize方法之外声明了一个实例变量@foo,并使其按我的预期工作: class FooBar def initialize(bar) @bar = bar end def foo_as_instance_var @foo = @bar.split(' ') @foo

我被教导使用
def initialize
声明我的实例变量。我一直认为我只能在
initialize
方法中声明实例变量

尽管如此,我还是在我的
initialize
方法之外声明了一个实例变量
@foo
,并使其按我的预期工作:

class FooBar
    def initialize(bar)
        @bar = bar
    end

    def foo_as_instance_var
        @foo = @bar.split(' ')
        @foo
    end
end

x = "something wicked this way comes"
y = FooBar.new(x)
puts y.foo_as_instance_var
为什么我能够在
initialize
方法之外声明实例变量?既然我可以在任何方法中声明实例变量,那么关于在何处声明实例变量(即在
initialize
中声明它们),我是否应该遵循一条最佳实践规则?这无关紧要吗

我已经学会用def initialize声明我的实例变量

由于
initialize
是对象生命周期中的第一个实例方法调用,因此通常在此处声明实例变量,以确保正确初始化变量。这也是我在阅读代码时希望定义实例变量的第一个地方

我的印象是,我只能在initialize方法中声明实例变量

没有这样的限制。您可以在实例中的任何位置声明实例变量

一个常见的用途是:

在第一次调用时,这将评估
昂贵的\u操作
,并将结果分配给
@foo
。在后续调用中,将返回
@foo

另一个流行的例子是Rails,它使用实例变量将数据从控制器传递到其视图:

class FooController < ApplicationController
  def index
    @foos = Foo.all
  end
end
class FooController
关于在何处声明实例变量,是否有我应该遵循的最佳实践规则


这取决于他们的目的(见上面的例子)。作为一般规则,以避免未定义变量(
nil
错误)的方式声明它们,并构造代码,使其易于阅读/理解。

这只是为了补充Stefan的优秀答案

我被教导使用
def initialize

ruby新手犯的一个常见错误如下:

class Person
  @name = "John"

  def introduce
    puts "Hi, my name is #{@name}"
  end
end

然后他们想知道为什么他们的名字没有印出来。为了实现这一点,可以在初始值设定项中设置变量
@name
,就像指令中所说的那样。

让我们从最大的误称开始——在Ruby中,没有声明变量的单独步骤——变量在设置时声明

有什么区别?以Java为例:

public class Bicycle {

    private int cadence;
    private int gear;
    private int speed;

    public Bicycle(int startCadence, int startSpeed, int startGear) {
        gear = startGear;
        cadence = startCadence;
        speed = startSpeed;
    }
}
在初始化器(Bicycle)中设置它们之前,我们必须声明所有实例变量。Ruby中的相同代码如下所示:

class Bicycle
  def initialize(cadence, speed, gear)
    @cadence = cadence
    @speed = speed
    @gear = gear
  end
end
没有仅声明的赋值。Ruby甚至允许您访问未设置的实例变量

irb(main):003:0> @not_set
=> nil
在必须定义变量的语言中(通常)不能这样做*

我已经学会用def声明我的实例变量 初始化。我一直以为我可以申报 仅在初始化方法中使用实例变量

无意义。您可以在任何地方分配实例变量。从setter和mutator(改变对象的方法)到factory方法(返回实例的类方法)或任何您正在改变对象状态的地方,它通常在所有方面都可以完成

class Book 

  def initialize(title, author)
    @title = title
    self.author = author # calls the setter.
  end

  # A factory method
  def create_from_csv(filename)
    # ...
  end

  # A very contrived setter
  def author=(author)
    @author = "#{author.forename.upcase}. #{author.surname}"
  end

  # a mutator
  def out_of_print!
    @out_of_print = true
    @last_printed = Date.today
  end
end

但是,
initialize
方法是您应该处理初始化对象(duuh)的地方,因此是设置初始值的明显位置

没关系。做有意义的事。如果你认为这只会发生在你的生活中,那你的印象是错误的。有关在initialize之外使用实例变量的详细信息,请阅读。@anothermh我是。这个问题肯定一直萦绕在我的脑后……能够跨实例方法访问,这就是实例变量的全部意义。@anothermh lol,我真的忘记或错过了
attr\u accessor
。谢谢如果只允许您在
initialize
中为实例变量赋值,那么您永远无法更改它们,除非再次调用
initialize
。谁告诉你的?另外,
initialize
只是一个与其他方法类似的方法,因此如果不允许在方法中为实例变量赋值,那么也不能在
initialize
中为它们赋值。您可以在
initialize
中分配它们的事实已经证明您可以在方法中分配它们,因为
initialize
是一种方法。这个完整的语句毫无意义。*除非您谈论的是Javascript,它是一个非常特殊的雪花。“未设置的access实例变量没有错误”-但是会有一个警告(如果启用)。
class Book 

  def initialize(title, author)
    @title = title
    self.author = author # calls the setter.
  end

  # A factory method
  def create_from_csv(filename)
    # ...
  end

  # A very contrived setter
  def author=(author)
    @author = "#{author.forename.upcase}. #{author.surname}"
  end

  # a mutator
  def out_of_print!
    @out_of_print = true
    @last_printed = Date.today
  end
end