Skip to content

Instantly share code, notes, and snippets.

@kevinclcn
Last active August 25, 2022 08:21
Show Gist options
  • Select an option

  • Save kevinclcn/50fd9eadcde972ba342e to your computer and use it in GitHub Desktop.

Select an option

Save kevinclcn/50fd9eadcde972ba342e to your computer and use it in GitHub Desktop.
global variable, class variable, class instance variable, instance variable, local variable

Global variable

全局变量以$开头,它是全局可见的。Ruby内建的全局变量如$:$LOAD_PATH表示require读取文件时寻找的目录数组。

Class variable

类变量以@@开头,可被定义它的类以及其子类访问,也可被定义它的类和子类的实例访问。

class Example
  @@cls_var = "defined in Example"

  def self.cls_var
    @@cls_var
  end

  def inst_var
      @@cls_var
  end
end

puts Example.cls_var # => "defined in Example"
puts Example.new.inst_var # => "defined in Example"

class SubExample < Example
  @@cls_var = "modified in SubExample"
end

puts SubExample.cls_var # => "modified in SubExample"
puts SubExample.new.inst_var # => "modified in SubExample"

class variable并不真正属于类,而是属于类体系结构。

@@cls_var = 1

class Example
  @@cls_var = 2
end

puts @@cls_var # => 2

因为@@cls_var被定义在Object类上,而Example继承自Object,所以Example也共享了这个类变量。

class Example
  @@foo = ""
  def foo
    @@foo 
  end
end

class SubExample < Example
  @@foo = "hello"
end

puts Example.new.foo # => "hello

Example.new并不属于SubExample,竟然也被SubExample的修改所影响!

正因为很多地方都可以改变类变量,很难追踪是什么地方做了改变,所以不推荐使用它。

Instance variable

在类对象上定义的变量是实例变量以@开头,实例变量因为存在于在对象上,所以整个对象的类的继承链都可以使用。这与Java等静态语言不一样。

父类里定义的实例变量,子类方法可以使用:

class Example
  def def_inst_var
    @inst_var = "I am defined in Example"
  end
end

class SubExample < Example
  def inst_var
    @inst_var
  end
end

sub = SubExample.new
sub.def_inst_var
puts sub.inst_var # => "I am defined in Example"

子类里定义的变量,父类方法也可以使用:

class Example
  def inst_var
    @inst_var
  end
end

class SubExample < Example
  def def_inst_var
    @inst_var = "I am defined by SubExample"
  end
end

sub = SubExample.new

sub.def_inst_var
puts sub.inst_var # => "I am defined by SubExample"

Class Instance variable

类本身也是一种对象,它是Class类的实例,在类上定义的变量,叫类实例变量。类实例变量只能被类方法访问。

class Example
  @cls_inst_var = "class instance variable"
  def self.cls_inst_var
    @cls_inst_var
  end
end

puts Example.cls_inst_var # => "class instance variable"

类实例变量因为存放在类对象上,所以可以被继承链上的类方法访问到。比如子类定义的类实例变量,父类的类方法能访问:

class Example 
  def self.cls_inst_var
    @cls_inst_var
  end
end

class SubExample < Example
  @cls_inst_var = "class instance variable"
end

puts SubExample.cls_inst_var # => "class instance variable

Local variable

局部变量只属于当前的作用域,作用域的改变只取决于三个关键字:class, moduledef。跟Java等语言不同,for,if,while等关键字并不会改变作用域。

def test(ok)
  if ok
    a = "I am OK!"
  end
  puts a
end

test(false) # => ""
test(true)  # => "I am OK!"
@famince
Copy link
Copy Markdown

famince commented Feb 26, 2018

比如子类定义的类实例变量,父类的类方法能访问:

例子错了,父类不行

@famince
Copy link
Copy Markdown

famince commented Feb 26, 2018

子类里定义的变量,父类方法也可以使用:

这个也错了......

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment