子类化Ruby Built ins时会出现哪些可证明的问题?

时间:2017-07-13 15:25:48

标签: javascript ruby-on-rails ruby

考虑像

这样的Ruby代码
class Row < Hash
   def count_of_columns
      self.keys.length
   end
end

c['Col 1'] = 1
c['Col 2'] = 2
puts c.count_of_columns 
# 2 

和这样的JavaScript代码:

function Row() {}
Row.prototype.column_count = function() { 
  return Object.keys(this).length
}


class Row {  // has Object as prototype
  column_count() { 
    return Object.keys(this).length
  }
}

尽管这些对象在两种不同语言中的使用方式相似,但为什么说ruby builtins的子类化很棘手?我已经看到了“Beware Subclassing Ruby Builtins&#39;”中提到的一些设计注意事项,如果您不在程序中的运行时类型上进行分支,则可能没有这些问题。

是否还有其他原因让人们分享您为什么不直接从Ruby中的内置函数派生出来?具体的东西..谢谢..

1 个答案:

答案 0 :(得分:1)

当您对内置子类化时,您开始假设您的子类的行为与内置类似,但是当内置函数返回内置的另一个实例时,您希望它返回子类的另一个实例。但这只会在您提前考虑这种情况并定义方法时才会发生。处理这种情况的方法越多,您对子类的期望越多,导致您在子类中重新实现的方法列表越来越多。

例如,考虑一下您的Row实现。当你在你的行上拨打#select时,你会发生什么?它应该返回Row的另一个实例吗?如果您想要这种行为,那么您需要实现它。但是如果你得到那种行为,那么也许你希望#reject也返回Row的实例,以及......和... ......(虽然看到评论,有时你会得到你期望的实例!)

我认为一般来说,更好的解决方案是使用内置功能作为“数据”和一些使用适当方法保存数据的域概念。不要让外人操纵你的数据。

为了进一步阅读,您可以了解为什么Rails 5将其ActionController :: Parameters从继承Hash转换为包含Hash的独立对象。我找不到描述所涉及的所有内容的有用链接,因此here's讨论了一个初始拉取请求。