首页 > 解决方案 > ELI5:为什么你可以在类方法中调用类方法而不明确说明类本身?(红宝石/导轨)

问题描述

抱歉,标题有点令人困惑,但我刚刚发现了一些令人难以置信的东西。当你在类方法中调用类方法时,你不必self在它前面放一个来让它执行。我不明白为什么会这样。

例如,假设您有一个Food具有以下架构的模型类:

  create_table "foods", force: :cascade do |t|    
    t.string  "name", null: false
    t.string  "food_type", null: false
    t.datetime "expiration_date", null: false
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

class Food < ApplicationRecord
  def self.output_new
    new(name: 'marshmallow', food_type: 'snack')
  end
end

而不是写Food.newor self.new,简单地写new返回一个新创建的实例。使用 Eigenclass 语法编写方法也会产生相同的结果。这不仅限于,new但它几乎适用于所有适用的类方法create, delete, instance_methods,如 等。

我已经搜索过为什么会这样,但我真的不明白。有人可以解释为什么会发生这种情况以确保我没有产生幻觉吗?

谢谢!

标签: ruby-on-railsrubyoopclass-method

解决方案


每当你调用一个方法时,Ruby 首先检查它是否定义在self. 我知道只有一个例外——如果你有一个与方法同名的局部变量,它将引用局部变量:

def num; 1; end
num = 2
num # => 2

在这方面,类方法与实例方法相同。

更容易想到不能省略 self 的情况:

  • 例如,当使用 setter 方法self.foo = "bar"时,它是必需的,因为 Ruby 需要知道您不只是尝试设置局部变量(就像foo = "bar"那样):

    class Test
      attr_writer :foo
      def initialize
        self.foo = 1 # calls the setter method
        foo = 2 # creates a local variable
      end
    end
    
  • 当局部变量和方法(两者具有相同名称)之间存在歧义并且您想要调用该方法时:

    class Foo
      def self.a; 1; end
      def self.b
        a = 2
        a # references local variable
        self.a # calls method
        a() # can also call the method by writing out parens (removes ambiguity)
      end
    end
    
  • 什么时候self不是你希望它在那个范围内的。

    class Foo
      def self; a; 1
    end
    
    a # obviously doesn't work, it isn't defined here
    Foo.a # works
    
  • 当方法名称与保留字相同时(例如class

    def class_name
      class.name # syntax error, it thinks you want to define a class
      self.class.name # works 
    end
    

推荐阅读