【问题标题】:Generic with default value of nil泛型,默认值为 nil
【发布时间】:2021-07-23 00:54:32
【问题描述】:

我正在尝试创建一个通用类/结构初始化程序,它可以转换它接收的任何值并将其分配给它的 Double 属性。 (注意:下面的 as! 或 as? 模式只是为了节省空间。我实际上是在使用 this extension 来转换我的值。)

这里的想法是我希望能够混合整数、双精度、CGFloats 等(即数字泛型类型约束中的任何内容)并将它们全部作为双精度。它适用于其他情况,但我在这里遇到了问题。

在下面的精简示例中,我正在创建一个 Vector 类,如果我们只处理 2 个维度,z 属性应该可以为 nil。

struct Vector {
    
    var x: Double
    var y: Double
    var z: Double?
    
    public init<X: Numeric, Y: Numeric, Z: Numeric>(_ x: X, _ y: Y, _ z: Z? = nil){
        self.x = x as! Double
        self.y = y as! Double
        self.z = z as? Double
    }
}

var myVector = Vector(4, 3.4)

print("""
    \(myVector.x)
    \(myVector.y)
    \(myVector.z)
    """
)

问题是我收到一个错误,上面写着Generic parameter 'Z' could not be inferred

【问题讨论】:

  • 请注意,从 Swift 4 开始,Swift 就有一个原生的数字协议。您应该选择另一个名称来表示您的协议。 DoubleConvertible 之类的东西
  • 我觉得这里的前提有点可疑。您是否经常遇到需要以这种方式处理的不匹配类型的对/三对数?
  • 公平的问题。在我们的特定用例(教育和图形)中,用户会说,例如 color(0,0,125.6)。 125.6 可以由返回 Doubles 的 random(255) 函数输入。对于新程序员来说,Integer 和 Double 之间的区别并不清楚。额外的复杂性是我们正在与 Core Graphics 交互,它使用 CGFloats 而不是 Doubles。如果用户使用类型推断创建变量,浮点将始终被推断为 Double。将其传递到需要 CGFloats 的函数中,您会遇到错误。这对我们的 API 影响很大。

标签: swift generics


【解决方案1】:

我会用两个独立的初始化器来做这件事,其中一个不需要有一个未使用的泛型Z

struct Vector {
    var x: Double
    var y: Double
    var z: Double?
}

extension Vector {
    public init<X: Numeric, Y: Numeric>(_ x: X, _ y: Y) {
        self.init(x: x as! Double, y: y as! Double, z: nil as Double?)
    }
    
    public init<X: Numeric, Y: Numeric, Z: Numeric>(_ x: X, _ y: Y, _ z: Z? = nil) {
        self.init(x: x as! Double, y: y as! Double, z: z as? Double)
    }
}

【讨论】:

  • 当我尝试在操场上执行此操作时出现错误 -“无法将 'Swift.Int' (0x7fff8182dce0) 类型的值转换为 'Swift.Double' (0x7fff8182d9e8)。” @亚历山大
  • @Bharad 请参阅 OP 的说明:“(注意:下面的 as! 或 as? 模式只是用来节省空间。我实际上是在使用 this extension 来转换我的值。)”
猜你喜欢
  • 2018-09-12
  • 2021-09-11
  • 1970-01-01
  • 1970-01-01
  • 2011-02-14
  • 2022-08-05
  • 2011-06-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多