Swift - 如何声明一个接收范围内数字的方法



我想创建一个函数,该函数的数字参数应介于 0..100 % 之间

我认为强制执行这一点的最佳方法是使用FloatingPointType协议创建包装器类型,但是我收到编译错误

协议"FloatingPointType"只能用作泛型约束,因为它具有 Self 或关联的类型要求

struct Percent {
    init(val : FloatingPointType) {
        // enforce value is between 0..100
    }
}

func hideView(percent : Percent) {
  // percent is 0..100 at this point
.. do some work here
}

在编译时强制实施此条件的正确方法是什么?

更新:Swift 5.1 开始,使用"属性包装器"可以更轻松地实现这一点,例如参见 NSHipster 上的"实现值夹紧属性包装器"。

最简单的方法是定义一个包含 Double(或FloatInt)在所需范围内:

struct P {
    let val : Double
    init (val : Double) {
        // ...
    }
}

但是如果你想处理不同的浮点类型,那么你必须定义一个泛型类

struct Percent<T : FloatingPointType> {
    let val : T
    init(val : T) {
       self.val = val
    }
}

要比较还需要Equatable的值,请执行以下操作:

struct Percent<T : FloatingPointType where T: Equatable> {
    let val : T
    init(val : T) {
        if val < T(0) {
            self.val = T(0)
        } else if val > T(100) {
            self.val = T(100)
        } else {
            self.val = val
        }
    }
}

例:

let p = Percent(val: 123.4)
println(p.val) // 100.0

请注意,这也要求hideView()是通用的:

func hideView<T>(percent : Percent<T>) {
    // percent.val has the type `T` and is in the range
    // T(0) ... T(100)
}

您正在寻找的语言功能称为分部函数。分部函数是未为指定类型的所有可能参数定义的函数。例如,它们在 Haskell或 Scala 中可用,但在 Swift 中不可用。

因此,您能做的最好的事情是在运行时检查提供的值是否在有效范围内并采取相应的措施(例如,引发异常或返回错误)。

听起来您正在尝试在编译时强制执行不能将 0.0 到 100.0 范围之外的值传递给函数。你不能这么做。

你可以做的是编写函数,以便在传递超出范围的值时引发异常,或者向用户显示错误并在超出范围时返回。

将 Martin 的答案与 Swift 5 的更新相加:

struct Percentage<T: FloatingPoint> {
  let value: T
  init(value: T) {
    self.value = min(max(value, T(0)), T(100))
  } 
}

使用站点,您可以定义泛型类型,例如:

func updateCircleWith(percentage: Percentage<CGFloat>) {
  // percentage.value will be between 0 and 100 here
  // of course the CGFloat(0) and CGFloat(100)
}

最新更新