我意识到这个问题对于StackOverflow来说可能太哲学了,但是我想知道基类化内置类来扩展它们的功能是否被认为是“好的”Ruby风格。
E.g。
class Grades < Array
def sum
sum = 0
self.each do |num|
sum += num
end
return sum
end
def avg
self.sum/self.length
end
end
现在,Grades对象在构建时看起来像数组,但是具有我想要访问的额外的sum和avg函数。它是“更好”的风格,不是基类数组,而是将此功能添加到通用对象?
答案 0 :(得分:8)
是
一般来说,每个人都可以自由地“修补”Ruby中的所有内容,从你编写的类到比你写的更重要的类,到库类。
然而,一般的计算风格指南是,如果你的班级做了所有事情,它什么都不做。您的示例有效地访问each()
和length()
,但您的新Grades
类现在公开每个 Array
方法,包括那些你可能不想要的东西〜包括那些有一天可能会有一些cretin和猴子补丁!因此,如果您的Grades
课程非常公开(由整个课程使用),您可能需要考虑授权。
另一个指南 - 在某些语言中应用的比其他语言更多 - 是你永远不应该继承的,除非你覆盖一个方法,以实现多态。另一个规则是整个Ruby社区,包括我在内,都喜欢自由自在。
答案 1 :(得分:4)
对于这种情况,我会说子类化并不合适。子类应该是其超类的更具体的版本 - 例如,Fixnum
是特定类型的Integer
(它是以特定方式存储的小整数),这是特定类型的{{ 1}}(只有一些数字是整数),这是一种特定的Numeric
(只有表示数字的对象才是数字)。另一方面,您的Object
课程与Grades
完全相同,只是它可以计算更多关于自身的内容。
如果Array
限制了它存储的数据 - 例如,它只允许你插入0.0到1.0之间的数字(或0到100之间的整数,如果你愿意的话) - 它可能有意义继承Grades
。另一方面,直接拥有Array
子类Grades
也是有意义的,并将实际成绩保持在Object
属性中。
另一方面,添加Array
和sum
只是添加了对其他类型的数组同样有用的功能。对于此类通用功能,我只需将这些方法添加到avg
,这样您就不必担心在特定位置是否有普通Array
或Array
。
当然,这里有一些灰色区域 - 如果您建议添加Grades
方法将成绩转换为A到F等级字母,我不会那么不愿意继承{{1} }。这绝对是一个判断。但是对于这种通用性水平,我真的不认为子类化是合适的。
答案 2 :(得分:0)
在Ruby中,道德更自由。允许的是程序员认为的任何东西。实际上,修补现有类的猴子几乎是标准做法。除了其他两个答案所说的之外,让我把你的注意力转移到Ruby 2.0 refine
功能上,它允许你在更严格的边界内进行修补,而不用担心与其他代码发生不良的交互。
但在您的特定情况下,我认为您创建单独的类Grades
的决定可能是正确的。这只是一种直觉,我必须熟悉您的代码库才能肯定地说出来。不太重要的是,您是否将Grades
类设为Array
的子类,或者是否只给它一个属性@grade_array
,您将在其中存储实际成绩并将其存储到从Array
class委派您想要的方法。