Swift 中的一步对象创建和 属性 初始化?

One-step object creation and property initialization in Swift?

有没有办法将 属性 值分配给 class 实例,即使它不是 init 构造函数中的参数?例如,在 C# 中我可以这样做:

public class Student
{
   public string firstName;
   public string lastName;
}

var student1 = new Student();
var student2 = new Student { firstName = "John", lastName  = "Doe" };

关于 student2 的通知即使 class 中没有构造函数,我仍然可以在初始化期间赋值。

我在 documentation 中找不到您是否可以为 Swift 做这样的事情。如果没有,有没有办法在初始化时使用extensions扩展Studentclass赋值属性?

我正在寻找这个的原因是我可以将一堆实例添加到数组中而无需为每个学生实例显式创建变量,如下所示:

var list = new[] {
  new Student { firstName = "John", lastName  = "Doe" },
  new Student { firstName = "Jane", lastName  = "Jones" },
  new Student { firstName = "Jason", lastName  = "Smith" }
}

在 Swift 中有什么本机或优雅的方法可以实现这一点?

如果您的 class 没有必需的初始化程序,您可以使用闭包方法在返回新的 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

根据您希望如何配置此类型以及您最方便的语法,您有几个选项。

您可以定义一个方便的初始化程序,它接受您要设置的属性。如果您始终设置相同的属性,则很有用;如果您设置的可选属性集不一致,则用处不大。

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( { [=11=].firstName = "Any"; [=11=].lastName = "Body" } )

您可以模仿 Ruby 的 tap 方法作为扩展,这样您就可以对方法链中间的对象进行操作。

extension Student {
    func tap(block: (Student) -> Void) -> Self {
        block(self)
        return self
    }
}

Student().tap({ [=12=].firstName = "Any"; [=12=].lastName = "body"})

如果最后一个有用,您可能希望能够在任何对象上采用 tap。我认为您不能自动执行此操作,但您可以定义一个默认实现以使其更容易:

protocol Tap: AnyObject {}

extension Tap {
    func tap(block: (Self) -> Void) -> Self {
        block(self)
        return self
    }
}

extension Student: Tap {}

Student().tap({ [=13=].firstName = "Any"; [=13=].lastName = "body"})

The reason I'm looking for this is so I can add a bunch of instances to an array without explicitly creating variables for each student instance[.]

我不熟悉 C#,但是在 Swift 中,您可以通过初始化数组声明中的对象来做到这一点:

var list: [Student] = [
    Student(firstName: "John", lastName: "Doe"),
    Student(firstName: "Jane", lastName: "Jones"),
    Student(firstName: "Jason", lastName: "Smith")
]

建议的其他方法都同样有效,但如果您只是想在不声明任何变量的情况下填充数组,Swift 会很容易。

我只是想指出,如果你的结构可以是不可变的,你可以只使用 struct 而不是 class,你将免费获得一个隐式初始化程序:

只需将其粘贴到 playground 并将结构更改为 class,您就会明白我的意思。

struct Student
{
    var firstName : String?
    var lastName : String?
}

var student = Student(firstName: "Dan", lastName: "Beaulieu")

这只是语法糖,但我使用自定义运算符来做这种事情:

 infix operator <- { associativity right precedence 90 }
 func <-<T:AnyObject>(var left:T, right:(T)->()) -> T
 {
   right(left)
   return left
 }

 let rgbButtons:[UIButton] = 
   [ 
     UIButton() <- { [=10=].backgroundColor = UIColor.redColor() },
     UIButton() <- { [=10=].backgroundColor = UIColor.greenColor() },
     UIButton() <- { [=10=].backgroundColor = UIColor.blueColor() }
   ]