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

时间:2016-01-22 22:04:02

标签: swift properties swift2 instance

有没有办法将属性值分配给类实例,即使它不是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中实现这一目标的任何原生或优雅方式?

5 个答案:

答案 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就可以轻松实现。