有没有办法将属性值分配给类实例,即使它不是init构造函数中的参数?例如,在C#中我可以这样做:
public class Student
{
public string firstName;
public string lastName;
}
var student1 = new Student();
var student2 = new Student { firstName = "John", lastName = "Doe" };
注意student2
我仍然可以在初始化期间分配值,即使类中没有构造函数。
我在documentation中找不到你是否可以为Swift做这样的事情。如果没有,有没有办法使用extensions
来扩展Student
类以在初始化期间分配属性值?
我正在寻找这个的原因是我可以在数组中添加一堆实例,而无需为每个学生实例显式创建变量,如下所示:
var list = new[] {
new Student { firstName = "John", lastName = "Doe" },
new Student { firstName = "Jane", lastName = "Jones" },
new Student { firstName = "Jason", lastName = "Smith" }
}
在Swift中实现这一目标的任何原生或优雅方式?
答案 0 :(得分:11)
您有几个选项,具体取决于您希望如何配置此类型以及最方便的语法。
您可以定义一个方便的初始化程序,它接受您要设置的属性。如果您一直在设置相同的属性,则非常有用,如果您正在设置一组不一致的可选属性,则无用。
public class Student
{
public var firstName:String?;
public var lastName:String?;
}
extension Student {
convenience init(firstName: String, lastName: String) {
self.init()
self.firstName = firstName
self.lastName = lastName
}
}
Student(firstName: "Any", lastName: "Body")
您可以定义一个便捷初始值设定项,它接受一个块来配置新实例。
extension Student {
convenience init(_ configure: (Student) -> Void ) {
self.init()
configure(self)
}
}
Student( { $0.firstName = "Any"; $0.lastName = "Body" } )
您可以模仿Ruby的tap
方法作为扩展,这样您就可以在方法链的中间操作对象。
extension Student {
func tap(block: (Student) -> Void) -> Self {
block(self)
return self
}
}
Student().tap({ $0.firstName = "Any"; $0.lastName = "body"})
如果最后一个有用,您可能希望能够对任何对象采用tap
。我不认为您可以自动执行此操作,但您可以定义默认实现以使其更容易:
protocol Tap: AnyObject {}
extension Tap {
func tap(block: (Self) -> Void) -> Self {
block(self)
return self
}
}
extension Student: Tap {}
Student().tap({ $0.firstName = "Any"; $0.lastName = "body"})
答案 1 :(得分:5)
如果您的类没有必需的初始化程序,则可以在返回新的Student对象之前使用闭包方法设置Student属性,如下所示:
public class Student {
var firstName = String()
var lastName = String()
}
let student1 = Student()
let student2: Student = {
let student = Student()
student.firstName = "John"
student.lastName = "Doe"
return student
}()
print(student2.firstName) // John
print(student2.lastName) // Doe
答案 2 :(得分:2)
我只是想指出,如果你的结构可以是不可变的,你可以使用struct
而不是class
,你将获得免费的隐式初始化器:
只需将其粘贴到游乐场并将结构更改为类,您就会明白我的意思。
struct Student
{
var firstName : String?
var lastName : String?
}
var student = Student(firstName: "Dan", lastName: "Beaulieu")
答案 3 :(得分:2)
这只是语法糖果,但我使用自定义运算符来执行此类操作:
infix operator <- { associativity right precedence 90 }
func <-<T:AnyObject>(var left:T, right:(T)->()) -> T
{
right(left)
return left
}
let rgbButtons:[UIButton] =
[
UIButton() <- { $0.backgroundColor = UIColor.redColor() },
UIButton() <- { $0.backgroundColor = UIColor.greenColor() },
UIButton() <- { $0.backgroundColor = UIColor.blueColor() }
]
答案 4 :(得分:1)
我正在寻找这个的原因是我可以向数组中添加一堆实例,而无需为每个学生实例显式创建变量[。]
我不熟悉C#,但在Swift中,只需初始化数组声明中的对象即可:
var list: [Student] = [
Student(firstName: "John", lastName: "Doe"),
Student(firstName: "Jane", lastName: "Jones"),
Student(firstName: "Jason", lastName: "Smith")
]
建议的其他方法都同样有效,但如果您只是尝试填充数组而不声明任何变量,Swift就可以轻松实现。