8

我需要一个类似于 Hash 的类,尽管不一定具有所有 Hash 方法。我已经读过,对像 Hash 这样的核心类进行子类化并不是一个好主意。不管这是否属实,做这种事情的最佳做法是什么?

# (a) subclass Hash, add new methods and instance variables
class Book < Hash
   def reindex
     @index = .....
   end
end

# (b) create a new class from scratch, containing a hash, 
#    and define needed methods for the contained hash
class Book
  def initialize(hash)
    @data = hash
  end 
  def []=(k,v)
    @data[k] = v
  end
  # etc....
  def reindex
    @index = ....
  end

# (c) like (b) but using method_missing

# (d) like (b) but using delegation

我意识到 Ruby 有不止一种方法来完成给定任务,但是在相对简单的情况下,对于上述哪种方法更可取,有什么通用规则吗?

4

1 回答 1

15

如果我绝对不希望类哈希对象具有某些哈希方法,那么我会将对象包装在我自己的类中,并且只公开我希望它具有的方法(您的选项 b)。

如果我希望它通过一些添加行为来保持其真正的哈希行为,我会在模块中将该行为添加到哈希对象本身,而不是修改核心哈希类:

module SpecialHash
  def reindex
    # method def
  end
end

my_hash = {}
my_hash.extend(SpecialHash)
my_hash.reindex #now is defined on my hash

最常见的是,这些选项之一对我有用。

一般来说,我倾向于使用模块来扩展类行为而不是类继承,因为我认为它是一种更简洁、更轻量级的方法。创建一个新类总是让我觉得我正在向我的领域模型添加一个新的“东西”。这很好,这正是您在无数场景中想要做的,但是当您实际上不需要走那么远时,Ruby 的 mixin 功能为您提供了一个非常好的选择。

我处理创建类的主要时间是我想要跟踪的对象中是否有一些额外的状态。如果我的补充不是关于扩展对象的状态,而只是扩展它的行为,那么我几乎总是会从使用模块将该行为混合到该类的现有实例中开始。

这类问题的另一个答案也提出了一些值得牢记的其他要点: ruby 继承 vs mixins

于 2013-01-06T21:13:06.137 回答