在`initialize`方法之外声明一个实例变量

时间:2019-01-15 04:24:30

标签: ruby initialization instance-variables

我被教导要用def initialize声明我的实例变量。我一直觉得我只能在initialize方法中声明实例变量。

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

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中声明实例变量)是否应该遵循最佳实践规则?

3 个答案:

答案 0 :(得分:4)

  

有人教我用def initialize声明实例变量

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

  

我一直以为只能在我的initialize方法中声明实例变量。

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

常见用法是memoization

class FooBar
  def foo
    @foo ||= expensive_operation
  end
end

在第一次调用时,它将评估expensive_operation并将结果分配给@foo。在随后的调用中,将返回@foo

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

class FooController < ApplicationController
  def index
    @foos = Foo.all
  end
end
  

关于在哪里声明实例变量,我是否应该遵循最佳实践规则

这取决于它们的用途(请参见上面的示例)。通常,以避免未定义变量(nil错误)的方式声明它们并构造代码,以使其易于阅读/遵循。

答案 1 :(得分:3)

只需添加Stefan的出色答案

  

我被教过用def initialize声明我的实例变量

红宝石新手犯的一个常见错误是这样的:

class Person
  @name = "John"

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

然后他们想知道为什么不打印他们的名字。为了使这项工作有效,可以按照指令中的说明在初始化程序中设置变量@name

答案 2 :(得分:2)

让我们从最大的误称开始-在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声明实例变量   初始化。我一直觉得我可以宣布   实例变量仅在我的initialize方法中。

无意义。。您可以在任何地方分配实例变量。它通常在从设置器和更改器(更改对象的方法)到工厂方法(返回实例的类方法)或要更改对象状态的任何地方完成。

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)的地方,因此很显然是设置初始值的地方。