我使用Swift创建了大量的结构体,所有结构体都遵循相同的模式。每个结构包含许多具有getter和setter的计算属性,每个结构类型之间的唯一区别是计算属性的数量以及每个结构的名称和类型。例如,
struct Employee
{
var title: String
{
get { /*...*/ return someDict["title"] as! String }
set { /*...*/ }
}
var id: Int
{
get { /*...*/ return someDict["id"] as! Int }
set { /*...*/ }
}
var salary: Double
{
get { /*...*/ return someDict["salary"] as! Double }
set { /*...*/ }
}
}
struct Student
{
var name: String
{
get { /*...*/ return someDict["name"] as! String }
set { /*...*/ }
}
var gpa: Double
{
get { /*...*/ return someDict["gpa"] as! Double }
set { /*...*/ }
}
}
现在,每个getter和setter在不同的结构中几乎完全相同,唯一的区别是每个都引用了计算属性名称及其类型的硬编码字符串表示。
这有点麻烦和重复。很难只看一下结构并查看它包含的属性,并涉及大量重复的代码。我考虑过制作一个具有所需属性的协议并在结构中采用,这样至少协议会更具可读性,但它并没有解决重复的代码问题。我想要做的是定义像定义这些属性的宏,比如
#define PROPERTY(NAME, TYPE) var NAME: TYPE { get{...} set{...} }
然后每个结构都可以更具可读性,并且重复代码的重复次数要少得多,例如,
struct Employee
{
PROPERTY(title, String)
PROPERTY(id, Int)
PROPERTY(salary, Double)
}
struct Student
{
PROPERTY(name, String)
PROPERTY(gpa, Double)
}
有没有办法在Swift中做这样的事情?或者我应该考虑更好的方法吗?我喜欢纯粹的Swift解决方案,因为我在Linux上运行(不完整的基础)。
答案 0 :(得分:1)
我能想出的最好的方法是创建一个外部脚本,它将某种简化模板作为输入,并吐出一个.swift文件,作为预编译构建阶段运行。类似的东西:
Input.notswift:
extension Employee {
PROPERTY(title, String, "title")
}
然后运行(类似,转义是完全错误的)作为预编译构建阶段:
sed s/PROPERTY\(([^,]*), ([^,]*), ([^,]*)\)/var NAME: TYPE { get{...} set{...} }/ < Input.notswift > Properties.swift
或者,您可以在Input.notswift上手动运行C预处理器以生成Input.swift。一旦你决定采用预处理方法,就可以使用无穷无尽的机制列表来从.notswift生成.swift。