在这个ruby示例中.self的用法是什么

在这个ruby示例中.self的用法是什么,ruby,Ruby,我一直在读我的课本,我们来上课,关键词self出现了。我一直在读一些关于tutorialpoint的教程,也读了很多问题,但由于某种原因,它并没有在我的脑海中出现,所以我决定用一些例子来修补一下 考虑 class Box # Initialize our class variables @@count = 0 def initialize(w,h) # assign instance avriables @width, @height = w, h

我一直在读我的课本,我们来上课,关键词
self
出现了。我一直在读一些关于tutorialpoint的教程,也读了很多问题,但由于某种原因,它并没有在我的脑海中出现,所以我决定用一些例子来修补一下

考虑

class Box
   # Initialize our class variables
   @@count = 0
   def initialize(w,h)
      # assign instance avriables
      @width, @height = w, h

      @@count += 1
   end

   def self.printCount()
      puts "Box count is : #@@count"
   end

end

# create two object
box1 = Box.new(10, 20)
box2 = Box.new(30, 100)

# call class method to print box count
Box.printCount()
如果从
printCount()
方法中删除
self.
,为什么会出现错误?我知道,
self
对于区分类变量和实例变量很重要,比如在我的示例中,
@width、@height
@@count

因此,我认为,由于我试图修改类变量
@@count
,我需要使用
.self
关键字,因为我试图修改类变量。因此,每当我们想要更改一个类变量时,我们必须使用
def self.methodName
格式


我的思维过程正确吗?

这里使用的方法有两种:实例方法和类方法。正如您所知,Ruby是一种面向对象的编程语言,所以一切都是对象。每个对象都有自己可以调用的方法。让我们看看你的代码

class Box
   # Initialize our class variables
   @@count = 0
   def initialize(w,h)
      # assign instance avriables
      @width, @height = w, h
      @@count += 1
   end

   def self.printCount()
      puts "Box count is : #@@count"
   end

end
使用
self.method\u name
创建方法时,您正在为类本身创建方法。因此,
Box
的对象有一个名为
printCount()
的方法。这就是为什么您可以直接调用该方法

Box.printCount()
但是,如果声明类
Box
的新实例,调用printCount()将导致错误

box1 = Box.new(1,1)
box1.printCount() #=> undefined method `printCount'
这是因为
box1
是类
Box
的一个实例,而
printCount
方法只能由类
Box
访问

如果在方法
printCount
之前删除
self
,它将成为一个实例方法,然后
box1
将有权访问该方法,但类
将不会

还有一些语义,Ruby使用snake_case作为方法名,因此
printCount
应该是
print_count
。这只是标准实践,并不真正影响代码的运行方式

另外,您需要小心使用类变量,即
@@count
。在Ruby中,它们的行为与您期望的不同。它不仅属于它在其中声明的类,它还是它的任何子类的一部分

例如,假设我定义了一个新的类调用
SmallBox
,并从
Box
继承

box1 = Box.new(1,1)
box1 = Box.new(1,1)
现在,对于
,计数应该是2。但是,如果您试图从我的新类访问
@@count

class SmallBox < Box
   p @@count
end

这里使用的方法有两种:实例方法和类方法。正如您所知,Ruby是一种面向对象的编程语言,所以一切都是对象。每个对象都有自己可以调用的方法。让我们看看你的代码

class Box
   # Initialize our class variables
   @@count = 0
   def initialize(w,h)
      # assign instance avriables
      @width, @height = w, h
      @@count += 1
   end

   def self.printCount()
      puts "Box count is : #@@count"
   end

end
使用
self.method\u name
创建方法时,您正在为类本身创建方法。因此,
Box
的对象有一个名为
printCount()
的方法。这就是为什么您可以直接调用该方法

Box.printCount()
但是,如果声明类
Box
的新实例,调用printCount()将导致错误

box1 = Box.new(1,1)
box1.printCount() #=> undefined method `printCount'
这是因为
box1
是类
Box
的一个实例,而
printCount
方法只能由类
Box
访问

如果在方法
printCount
之前删除
self
,它将成为一个实例方法,然后
box1
将有权访问该方法,但类
将不会

还有一些语义,Ruby使用snake_case作为方法名,因此
printCount
应该是
print_count
。这只是标准实践,并不真正影响代码的运行方式

另外,您需要小心使用类变量,即
@@count
。在Ruby中,它们的行为与您期望的不同。它不仅属于它在其中声明的类,它还是它的任何子类的一部分

例如,假设我定义了一个新的类调用
SmallBox
,并从
Box
继承

box1 = Box.new(1,1)
box1 = Box.new(1,1)
现在,对于
,计数应该是2。但是,如果您试图从我的新类访问
@@count

class SmallBox < Box
   p @@count
end

我想提供一个更具体的定义来澄清查找算法

首先,让我们定义
self
。Ruby中的self是一个特殊变量,它总是引用当前对象。当前对象(self)是方法调用的默认接收方。其次,self是发现实例变量的地方

class MyClass
  def method_one
    @var = 'var'
    method_two
  end
  def method_two
    puts "@var is #{@var}"
  end
end

obj = MyClass.new
obj.method_one
上面,当我们调用方法_one时,self将引用实例化的对象,因为我们在显式接收器(对象实例)上调用了方法_one。因此类中方法定义中的self.method_one将引用对象实例,而不是类对象本身@var将存储在self中。请注意,当调用方法_two时,由于没有默认接收器,因此接收器是self。因此,当调用方法_two时,我们保持在同一个对象实例中。这就是为什么方法二中的@var将引用方法一中相同的@var。它是同一个物体

Ruby支持继承。因此,如果我们在self上调用一个方法,而它没有在其类中定义,那么Ruby将在超类中搜索实例方法。这种情况会一直持续到Ruby到达BasicObject。如果在任何超类中都找不到该方法,则会引发NoMethodError

现在,继承链还有另一个重要部分。有一个名为singleton的匿名类,Ruby将把它注入到这个继承链中。继承链在哪里?它将其插入到对象的原始类之前。这样,当ruby搜索方法时,它将在命中ob的原始类之前命中singleton类
class HelloWorld
  def self.say_hi_from_singleton_class
    puts 'Hello World from the Singleton Class'
  end
end

HelloWorld.say_hi_from_singleton_class
HelloWorld -> Anonymous Singleton Class -> Class (this is where the new method is defined) -> Module -> Object
> puts self
main
> class HelloWorld
>   puts self
> end
HelloWorld
 => nil 
> puts self
main