我需要一个类似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有多种方法可以完成给定的任务,但是在相对简单的情况下,是否有任何一般规则可以解决上述哪种方法?
答案 0 :(得分:14)
如果我绝对不希望Hash类对象拥有某些哈希方法,那么我会将该对象包装在我自己的类中,并且只公开我想要它的方法(你的选项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 inheritance vs mixins