【发布时间】:2014-06-02 20:09:15
【问题描述】:
在构造时抛出异常通常被认为不是一件很有礼貌的事情,但我不确定在尝试对案例类值强制执行约束时如何避免这种情况。
例如,我需要表示一个范围,并且两个边界都必须是正数。立即实施是:
case class Range(from: Int, to: Int)
然而,这并不能确保from 和to 都是正数,也不能确保to 大于from。
我的第一反应是按如下方式实现:
case class Range(from: Int, to: Int) {
require(from >= 0)
require(to >= 0)
require(to >= from)
}
然而,这使得Range 的构造函数不安全。
是否有一种通用模式来保持案例类的易用性、强制值约束并避免抛出异常?
【问题讨论】:
-
"强制值约束,避免抛出异常?" - 强制执行是什么意思?当有人尝试使用无效的 from/to 构造 Range 时,您希望发生什么?
-
谢谢保罗,这是我问题的关键。我应该做什么?我试图防止创建无效实例,并且似乎有一个共识,即构造函数或构造方法不应该抛出。我不知道如何做一个没有另一个,有没有我没有看到的解决方案?
-
理想主义的答案是类型级编程(但学习曲线陡峭)。创建这样的东西应该是编译时错误。但是,如果不这样做,您似乎有四种选择:忽略问题(接受无效参数),抛出异常,强制参数有效范围,使用标志将实例标记为无效(并在调用任何方法时抛出异常)它?)。我,我会在构造函数中抛出一个异常......
-
"用标志将实例标记为无效(并在调用任何方法时抛出异常?)。" - 一个变体:返回 Range 的 InvalidRange 子类(或对象),该子类在所有内容上都会出错。
-
我非常喜欢您的最后一个建议,它干净且类型安全,而且一切都很好。它只是与我根深蒂固的“快速失败”反射相冲突,如果我知道发生了不应该发生的事情,我应该立即失败,而不是尝试返回(可能不正确的)结果。
标签: scala