gpt4 book ai didi

swift - 如何在 Swift 中正确支持 CGFloat 数学中的 Int 值?

转载 作者:行者123 更新时间:2023-11-28 09:16:48 26 4
gpt4 key购买 nike

目标

我(像网络上的许多其他人一样)想使用 Int CGFloat 中的变量和文字数学,因为可读性和易于开发远远超过了可能的精度损失。当您在整个应用程序中使用手动布局而不是使用 Storyboard 时,这一点最为明显。

因此,以下内容应该可以在没有任何手册的情况下工作 CGFloat类型转换:

let a = CGFloat(1)
let b = Int(2)

let c = a / b // Cannot invoke / with an arguments list of type (CGFloat, Int)
let d = b / a // Cannot invoke / with an arguments list of type (Int, CGFloat)
let e = a / 2 // => CGFloat(0.5)
let f = 2 / a // => CGFloat(2.0)
let g = 2 / b // => Int(1)
let h = b / 2 // => Int(1)
let i = 2 / 2 // => Int(1)
let j: CGFloat = a / b // Cannot invoke / with an arguments list of type (CGFloat, Int)
let k: CGFloat = b / a // Cannot invoke / with an arguments list of type (Int, CGFloat)
let l: CGFloat = a / 2 // => CGFloat(0.5)
let m: CGFloat = 2 / a // => CGFloat(2.0)
let n: CGFloat = 2 / b // Cannot invoke / with an arguments list of type (IntegerLiteralConvertible, Int)
let o: CGFloat = b / 2 // Cannot invoke / with an arguments list of type (Int, IntegerLiteralConvertible)
let p: CGFloat = 2 / 2 // => CGFloat(1.0)

方法

由于我们无法向 Swift 类型添加隐式转换,因此我必须添加适当的运算符,这些运算符采用 CGFloatInt .
func / (a: CGFloat, b: Int) -> CGFloat { return a / CGFloat(b) }
func / (a: Int, b: CGFloat) -> CGFloat { return CGFloat(a) / b }

问题

当 Swift 试图隐式创建 CGFloat 时,这两个运算符变得模棱两可。来自整数文字的值。它不知道要转换两个操作数中的哪一个(示例案例 p )。
let a = CGFloat(1)
let b = Int(2)

let c = a / b // => CGFloat(0.5)
let d = b / a // => CGFloat(2.0)
let e = a / 2 // => CGFloat(0.5)
let f = 2 / a // => CGFloat(2.0)
let g = 2 / b // => Int(1)
let h = b / 2 // => Int(1)
let i = 2 / 2 // => Int(1)
let j: CGFloat = a / b // => CGFloat(0.5)
let k: CGFloat = b / a // => CGFloat(2.0)
let l: CGFloat = a / 2 // => CGFloat(0.5)
let m: CGFloat = 2 / a // => CGFloat(2.0)
let n: CGFloat = 2 / b // => CGFloat(1.0)
let o: CGFloat = b / 2 // => CGFloat(1.0)
let p: CGFloat = 2 / 2 // Ambiguous use of operator /

问题

有没有办法以一种没有歧义并且所有测试用例都成功的方式声明运算符?

最佳答案

对于初学者, tl;博士:否 .

问题是我们要求编译器隐式地做太多事情。

我将使用常规函数来回答这个问题,因为我希望清楚这与运算符无关。

因此,我们需要以下 4 个函数:

func foo(a: Int, b: Int) -> Int {
return 1
}

func foo(a: Int, b: Float) -> Float {
return 2.0
}

func foo(a: Float, b: Int) -> Float {
return 3.0
}

func foo(a: Float, b: Float) -> Float {
return 4.0
}

现在我们处于同样的情况。我将忽略所有有效的方法并专注于这两种情况:
let bar1 = foo(1,2)
let bar2: Float = foo(1,2)

在第一个场景中,我们要求 Swift 隐式地​​确定一件事:应该是什么类型 bar1是?我们传递给 foo 的两个参数是 1 ,其类型为 IntegerLiteralConvertible , 和 2 ,它又是 IntegerLiteralConvertible 类型.

因为 foo 只有一个覆盖这需要两个 Int参数,Swift 能够找出是什么类型 bar1应该是,这就是 foo(Int,Int) 的任何类型覆盖返回,即 Int .

现在,考虑我们添加以下函数的场景:
func foo(a: Int, b: Int) -> Float {
return 5.0
}

现在,场景 1 变得模棱两可:
let bar1 = foo(1,2)

我们要求 Swift 在这里隐式地确定两件事:
  • foo 的哪个覆盖使用
  • bar1 使用什么类型

  • 满足场景的方法不止一种。 bar1Int我们使用 foo(Int,Int)->Int覆盖,或 bar2Float , 我们使用 foo(Int,Int)->Float覆盖。编译器无法决定。

    尽管这样,我们可以使情况不那么模棱两可:
    let bar1: Int = foo(1,2)

    在这种情况下,编译器知道我们想要 foo(Int,Int)->Int覆盖——它是唯一满足场景的。或者我们可以这样做:
    let bar2: Float = foo(1,2)

    在这种情况下,编译器知道我们想要 foo(Int,Int)->Float覆盖——再次,满足场景的唯一方法。

    但是让我们回顾一下我的场景 2,这正是您遇到的问题场景:
    let bar2: Float = foo(1,2)

    没有 foo(Int,Int)->Float覆盖(忘记我们添加此覆盖的场景 1 的所有内容)。但是,类型 IntegerLiteralConvertible可以隐式转换为不同类型的数值数据类型(只有文字整数......不是整数变量)。所以编译器会尝试找到 foo覆盖 IntegerLiteralConvertible 的参数可以转换为并返回 Float ,我们已明确标记为 bar2的类型。

    好吧, IntegerLiteralConvertible可以转换为 Float ,因此编译器会找到三个采用正确参数组合的函数:
  • foo(Int,Float) -> Float
  • foo(Float,Int) -> Float
  • foo(Float,Float) -> Float

  • 并且编译器不知道使用哪个。怎么可能?为什么它应该优先将一个或另一个文字整数转换为浮点数?

    所以我们得到了歧义问题。

    我们可以给编译器另一个覆盖。这与我们在场景 2 中给出的相同: foo(Int,Int) -> Float ,现在编译器可以使用以下内容:
    let bar2: Float = foo(1,2)

    因为在这种情况下,没有隐式转换 IntegerLiteralConvertibles ,编译器能够找到匹配的函数: foo(Int, Int) -> Float .

    所以现在你在想:

    All right, let me just add this foo(Int,Int)->Float and everything will work!



    对?

    好吧,很抱歉让您失望了,但考虑到以下两个功能:
    foo(Int,Int) -> Int
    foo(Int,Int) -> Float

    我们仍然会遇到歧义问题:
    let bar3 = foo(1,2)
    foo 有两个覆盖采取 Int (或 IntegerLiteralConvertible ),因为我们没有指定 bar3的类型,我们要求编译器找出适当的覆盖并隐式确定 bar3的类型,这是它做不到的。

    关于swift - 如何在 Swift 中正确支持 CGFloat 数学中的 Int 值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27173744/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com