为复数创建我自己的自动装箱 class

Creating my own autoboxed class for complex numbers

所以众所周知,在Swift声明一个class,你说 let variable = ClassName(parameters) 然而,要声明像数组和整数这样的东西,你可以只说 let variable = 32(而不是 Int(32)) let variable = [3,2,4](而不是 let variable = Array<Int>(3,2,4)

假设我想为可以这样声明的复数(虚数)创建一个 class:

let complexNumber = 5i

let complexNumber = 3i

请注意,复数不一定是问题的重点,让您自己拆箱是

Swift 文字

在 Swift 中,您描述的这些语法称为“文字”,这是初始化符合特定协议集的类型值的便捷方式。文字的语法不是 user-extensible,因为它依赖于 Swift 解析器来理解如何解析它们。支持的是:

Literal Protocol
Integer ExpressibleByIntegerLiteral
Floating-Point ExpressibleByFloatLiteral
String ExpressibleByStringLiteral
Extended Grapheme Cluster ExpressibleByExtendedGraphemeClusterLiteral
Unicode Scalar ExpressibleByUnicodeScalarLiteral
Boolean ExpressibleByBooleanLiteral
Nil ExpressibleByNilLiteral
Array ExpressibleByArrayLiteral
Dictionary ExpressibleByDictionaryLiteral

(参见 NSHipster's article about literals for more details)。

但我更广泛地理解您的观点:您想在 Swift 代码中以类似的方式表达来自另一个领域(例如数学)的语法,因此该领域的 subject-matter 专家很熟悉.

有很多解决方法,具体取决于具体问题。

对于您的复数示例,可以定义一个新的 Complex 类型,使用 * 运算符和 i 值,这样您就可以编写:

let complexNumber = 5 * i

有很多数字编程库(特别是 first-party swift-numerics,它们定义了此类类型(尽管语法不一定相同)。

您还可以看到 Apple 使用 SwiftUI 做了什么,使用 result-builders 构建了一个 Swift DSL 来雄辩地描述视图层次结构。

奖金:这不是“拳击”

这里没有拳击比赛。我怀疑您来自 Java 背景,其中装箱是分配对象以存储原始类型的过程,因为只有这样它们才能传递到对象中(例如存储到像 [=15= 这样的容器中) ]).

Swift 并非如此。没有“原始”类型。有引用类型(类 和 class-bound 协议存在的实例)和值类型(结构、枚举和协议存在)。 Swift 的具体化泛型可以处理类似的值和引用对象,例如Int 可以直接进入 Array<Int>。所以大多数时候,没有拳击可做。

有些地方 Swift 遇到了使 Java 需要装箱值的相同问题:像数组这样的连续存储无法处理具有不同大小的元素,因此代码如下成为挑战:

let x: Array<Any> = [true, "abc", 123, someObject]

此外,还需要某种方式来表达如何处理不同类型的值(保留、释放、复制等)。

为了解决这些问题,编译器会自动生成代码,将这些值装箱到称为“存在容器”的箱子中,箱子存储这些值,table 函数指针描述可以对此值执行。虽然值的大小不同,但所有存在的容器都具有相同的大小,因此您可以用它们创建一个数组。