【问题标题】:Creating a method to be called on an array创建要在数组上调用的方法
【发布时间】:2018-01-15 17:19:12
【问题描述】:

test_cal 是自定义类的一个实例,get_calendar_items 返回一个数组。我想编写一个在数组上调用的方法,如下所示:

test_cal.get_calendar_items.get_subject

这是我写的方法

def get_subject(number)
    puts self[number].subject
end

但是,ruby 给出了一个错误:

undefined method get_subject for #<Array:0x00 ...> (NoMethodError)

如何编写可以在数组上调用的方法?

我假设每个数组都是某种对象。 然后在方法中通过number 访问数组的各个元素。

【问题讨论】:

  • number 来自哪里?当你调用它时,你不要把它给get_subject。你不应该说test_cal.get_calendar_items.get_subject(number)吗?那么为什么不直接做test_cal.get_calendar_items[number].subject呢?这是正常的方式。而且更短。
  • 在 Ruby 中为 getter 加上 get_ 前缀是不习惯的。只需调用方法calendar_items 或简单地调用items
  • 数组是任意对象的集合。因此,添加仅适用于特定元素的方法没有多大意义(您不必这样做,如上面的 Stefan Pochmann 所示)。更好的方法是为您的集合创建一个自定义类(例如CalenderItemArray)或extendget_calendar_items 返回的数组实例,因此您只需将“集合方法”添加到这些数组。

标签: ruby oop


【解决方案1】:

你必须在 Array 类中定义它

class Array
  def get_subject(number)
      puts self[number].subject
  end
end

由于您是 Ruby 新手,您应该知道这种方法不是很好,因为它很大程度上取决于存储在数组中的对象。例如,我可以使用[1].get_subject(0)["foo"].get_subject(0),但我会收到错误消息,因为数字和字符串没有subject 方法。

【讨论】:

  • 如果采用这种方法,我会将第 3 行修改为 puts self[number].subject if self[number].is_a?('CalendarItem')
  • nil 替换错误并不能解决问题。因为您才刚刚开始,所以暂时不要太担心它,但是还有更多惯用的方法可以做到这一点。
【解决方案2】:

尽管您可以定义 Array 实例方法来解决您的问题,但出于多种原因,定义 Core 类的方法被认为是一种不好的做法。更好的是 f.e.在test_cal 类中定义另一个从get_calendar_items 获取subject 的方法:

class TestCal # or whichever `test_cal` class is
  def get_calendar_items_subjects
    get_calendar_items.map &:subject
  end
end

然后:

test_cal.get_calendar_items_subjects[number]

【讨论】:

    【解决方案3】:

    通常,只有当 Array 是一种可以在所有数组上调用的方法时,您才会扩展它。由于主题是数组内容的先决条件,我认为添加如下所示的类方法会更好。

    class CalendarItem
      def self.get_subject(arr, index=0)
        arr[index].subject
      end
    end
    

    重组后的代码会变成

    CalendarItem.get_subject(test_cal.get_calendar_items)
    

    【讨论】:

    • @StefanPochmann 抱歉,我没有发现这篇文章不是针对 Rails 的。不错的收获。解决方案已修改。
    【解决方案4】:
    def get_subject(number)
      puts self[number].subject
    end
    

    您只需将上述方法调用如下:

    test_cal.get_calendar_items.each do |number|
      get_subject(number)
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-17
      • 2018-05-15
      • 1970-01-01
      • 2018-03-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多