【问题标题】:Trying to understand use of self.method_name vs. Classname.method_name in Ruby试图了解在 Ruby 中使用 self.method_name 与 Classname.method_name
【发布时间】:2009-05-14 14:52:42
【问题描述】:

我试图了解何时使用 self.method_name 与何时使用 Classname.method_name。

在下面的示例中,为什么“before_create”需要引用“User.hash_password”而不是“self.hash_password”或只是“hash_password”?

由于我们已经在 User 类中,我认为 before_create 方法会“知道”“hash_password”是它自己的类的成员,并且不需要任何特殊语法来引用它。

require 'digest/sha1'

class User < ActiveRecord::Base

  attr_accessor :password
  attr_accessible :name, :password

  validates_presence_of :name, :password
  validates_uniqueness_of :name

  def before_create
    self.hashed_password = User.hash_password(self.password)
  end

  def after_create
    @password = nil
  end

  def self.login(name, password)
    hashed_password = hash_password(password || "")
    self.find(:first, :conditions => ["name = ? and hashed_password = ?", name, hashed_password])
  end

  def try_to_login
    User.login(self.name, self.password)
  end

  private

  def self.hash_password(password)
    Digest::SHA1.hexdigest(password)
  end

end

【问题讨论】:

    标签: ruby


    【解决方案1】:
    def before_create
       self.hashed_password = User.hash_password(self.password)
    end
    

    在此示例中,User.hash_password 调用 User 上的 hash_password 方法,而 self.hashed_password= 调用 此特定实例上的 hashed_password= 方法User

    如果将User.hash_password 替换为self.hash_password,Ruby 会报错NoMethodError,因为类User 中不存在名称为hash_password 的实例方法。不过,您可以将其替换为 self.class.hash_password

    如果您将self.hashed_password= 替换为简单的hashed_password=,Ruby 将创建一个名为hashed_password 的局部变量,而不是调用实例方法hashed_password=。如果要调用属性编写器,则需要显式添加self

    方法定义中的self (def self.hash_password) 使hash_password 成为类方法而不是实例方法。在这种情况下,self 指的是 。在实例方法的上下文中,self 指的是一个实例

    【讨论】:

    • 因为最后几行定义了def self.hash_password(password),我以为self.hash_password指的是这个方法。但是你说 self.hash_password 会得到一个 NoMethodError - 即使方法定义说“self”。我不能用“自我”来指代它。令人困惑!
    • self.hashed_pa​​ssword= 调用属性编写器?但我没有定义属性编写器。是自动创建的吗?
    • self.hashed_pa​​ssword= 可能由 ActiveRecord 为您定义,如果您有一个名为“hashed_pa​​ssword”的数据库列。
    • "方法定义中的 self (def self.hash_password) 使 hash_password 成为类方法而不是实例方法。"所以我是对的:这是一种静态方法。而且没有代表爱。 :( :(
    【解决方案2】:

    你问的是类方法和实例方法的区别。

    定义类方法有几种方式:

    class Klass
      def Klass.method_name
        ..
      end
    end
    

    这和做的一样:

    class Klass
      def self.method_name
        ..
      end
    end 
    

    或首选的 ruby​​ 成语:

    class Klass
      class << self
        def method_name
          ..
        end
      end
    end
    

    如果已经声明了 Klass,你也可以这样做..

    def Klass.method_name
      ..
    end
    

    或:

    class << Klass
      def method_name
        ..
      end
    end
    

    或者你甚至可以使用 Module#extend:

    Klass.extend(Module.new { def method_name; puts 'ducky'; end })
    

    就像您将单例方法添加到对象一样。实际上类方法是在类级别上操作的单例方法。

    例如,在 rails ActiveRecord 中,您有一个可以在任何模型上使用的类方法“find”:

    Person.find(1) 
    

    以及对单个对象进行操作的“保存”等实例方法

    person = Person.find(1)
    ...
    person.save
    

    在我正在进行的当前项目中,我有一个模型 Feed,其中包含数据 Feed。我需要定期运行一个更新所有提要的方法,所以我有一个 fetch_all 方法来完成这个。

    class Feed < ActiveRecord::Base 
    
      // class method Feed.fetch_all
      def self.fetch_all
        Feed.all.each do |feed|
          feed.fetch_value
        end
      end
    
      // instance method
      def fetch_value
        // grabs updated value and saves 
      end
    end
    

    【讨论】:

      【解决方案3】:

      我还没有深入研究 Ruby,但根据您的描述,我会说 hash_password 是一种静态方法,或者能够以静态方式使用。

      【讨论】:

      • 没错。在ruby中,静态方法称为类方法
      猜你喜欢
      • 1970-01-01
      • 2011-01-02
      • 1970-01-01
      • 2016-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多