【问题标题】:Method_missing not running when it shouldMethod_missing 在应该运行时没有运行
【发布时间】:2016-08-19 01:46:29
【问题描述】:

我的程序中有一个 Team 类,我正在尝试使用 method_missing 但是当方法不存在时,它没有运行该函数,而是给了我一个错误:"undefined method `hawks' for Team:Class (NoMethodError)"

我的代码如下:

class Team
  attr_accessor :cust_roster, :cust_total_per, :cust_name, :cust_best_player
  @@teams = []
  def initialize(stats = {})
    @cust_roster = stats.fetch(:roster) || []
    @cust_total_per = stats.fetch(:per)
    @cust_name = stats.fetch(:name)
    @cust_best_player = stats.fetch(:best)
    @@teams << self

  end
  def method_missing(methId)
    str = methID.id2name
    Team.new(roster:[], per: 0, name: str.uppercase, best: 0)

  end



  class <<self
    def all_teams
      @@teams
    end
  end

end
hawks = Team.hawks

【问题讨论】:

  • 你不是说hawks = Team.new.hawks吗? Team.hawks 尝试调用不存在的类方法 hawks
  • 或者def self.method_missing
  • 不,这不起作用,因为 Team.new 已经是一个函数,它不会运行 method_missing
  • @ScottJ stack level too deep (SystemStackError)
  • 尝试做hawks = Team.new。然后做hawks = hawks.hawks

标签: ruby method-missing


【解决方案1】:

您的代码存在许多问题。让我们一一来介绍。

从文档中,

method_missing(*args) 私有 当 obj 收到无法处理的消息时由 Ruby 调用。

这里的message 指的是method。在 ruby​​ 中,每当你调用一个对象的方法时,你实际上是在 sendmessageobject

为了更好地理解这一点,请在 irb shell 中尝试一下。

1+2
=> 3
1.send(:+,2)
=> 3

这里 1 和 2 是 Fixnum 类的对象。您可以使用1.class 进行确认。好的,回到你的问题。因此,应该在实例上调用 method_missing 方法。

team = Team.new
team.hawks

如果你尝试上面的代码,你会得到一个错误提示'fetch': key not found: :roster (KeyError)

您可以通过将default value 作为第二个参数传递给fetch 方法来解决此问题。将您的 initialize 方法替换为

def initialize(stats = {})
  @cust_roster = stats.fetch(:roster, [])
  @cust_total_per = stats.fetch(:per, 0)
  @cust_name = stats.fetch(:name, "anon")
  @cust_best_player = stats.fetch(:best, "anon")
  @@teams << self

结束

如果你执行脚本,你会得到一个stack level too deep (SystemStackError),因为这行有一个小错字。

str = methID.id2name

在方法定义中,您收到名称为methId 的参数,但在内部您尝试调用methID。修复它

str = methId.id2name

如果你执行你的脚本,你会再次收到错误消息undefined method uppercase for "hawks":String (NoMethodError)

这是因为字符串上没有uppercase 方法。您应该改用upcase 方法。

Team.new(roster:[], per: 0, name: str.upcase, best: 0)

你应该很高兴。

欲了解更多信息,请参阅http://apidock.com/ruby/BasicObject/method_missing

希望这会有所帮助!

【讨论】:

    【解决方案2】:
    class Team
      attr_accessor :cust_roster, :cust_total_per, :cust_name, :cust_best_player
      @@teams = []
      def initialize(stats = {roster: [], per: 0, name: "", best: 0}) # I added the default values here. 
        @cust_roster = stats.fetch(:roster)
        @cust_total_per = stats.fetch(:per)
        @cust_name = stats.fetch(:name)
        @cust_best_player = stats.fetch(:best)
        @@teams << self
    
      end
      def method_missing(name, *args)
        self.cust_name = name.to_s.upcase
      end
    
      class << self
        def all_teams
          @@teams
        end
      end
    
    end
    
    team_hawks = Team.new #=> create an instance of Team class, I renamed the object to avoid confusions. 
    team_hawks.hawks      #=> called method_missing which assigned the cust_name variable to "HAWKS"
    
    team_hawks.cust_name  #=> HAWKS, so cust_name is assigned to be hawks. This is to check if the assignment worked. 
    

    希望这是您正在寻找的。

    【讨论】:

      猜你喜欢
      • 2022-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多