2016-01-22 49 views
6

Có cách nào để gán giá trị thuộc tính cho một cá thể lớp ngay cả khi nó không phải là tham số trong hàm tạo init? Ví dụ, trong C# tôi có thể làm điều này:Tạo đối tượng một bước và khởi tạo thuộc tính trong Swift?

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

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

Thông báo cho student2 tôi vẫn có thể gán giá trị trong quá trình khởi mặc dù không có constructor trong lớp.

Tôi không thể tìm thấy trong các documentation nếu bạn có thể làm một cái gì đó như thế này cho Swift. Nếu không, có cách nào để sử dụng extensions để mở rộng lớp Student để gán giá trị thuộc tính trong quá trình khởi tạo không?

Lý do tôi đang tìm kiếm này vì vậy tôi có thể thêm một loạt các trường hợp để một mảng mà không cần tạo một cách rõ ràng biến cho mỗi trường hợp sinh viên, như thế này:

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

Bất kỳ cách nào có nguồn gốc hoặc tao nhã để đạt được điều này trong Swift?

Trả lời

8

Bạn có một vài lựa chọn tùy thuộc vào cách bạn muốn để định cấu hình loại này và cú pháp nào thuận tiện nhất cho bạn.

Bạn có thể xác định trình khởi tạo thuận tiện chấp nhận thuộc tính bạn muốn đặt. Hữu ích nếu bạn đang thiết lập các thuộc tính giống nhau mọi lúc, ít hữu ích hơn nếu bạn đang đặt một tập hợp thuộc tính tùy chọn không nhất quán.

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") 

Bạn có thể xác định trình khởi tạo thuận tiện chấp nhận khối để định cấu hình phiên bản mới.

extension Student { 
    convenience init(_ configure: (Student) -> Void) { 
     self.init() 
     configure(self) 
    } 
} 

Student({ $0.firstName = "Any"; $0.lastName = "Body" }) 

Bạn có thể bắt chước phương pháp tap Ruby như một phần mở rộng, do đó bạn có thể hoạt động trên một đối tượng ở giữa một chuỗi phương pháp.

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

Student().tap({ $0.firstName = "Any"; $0.lastName = "body"}) 

Nếu mà cuối cùng là hữu ích, bạn có thể muốn để có thể áp dụng tap trên bất kỳ đối tượng. Tôi không nghĩ rằng bạn có thể làm điều đó tự động nhưng bạn có thể xác định một thực hiện mặc định để làm cho nó dễ dàng hơn:

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"}) 
+0

Đây là rực rỡ! – TruMan1

4

Nếu lớp học của bạn không có initialiser cần thiết, bạn có thể sử dụng một phương pháp đóng cửa để thiết lập các thuộc tính sinh viên trước khi trở về đối tượng sinh viên mới như sau:

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 
1

Lý do tôi đang tìm kiếm này vì vậy tôi có thể thêm một loạt các trường hợp để một [.] mảng mà không cần tạo một cách rõ ràng biến cho mỗi trường hợp sinh viên

tôi không quen với C#, nhưng trong Swift, bạn có thể làm điều đó chỉ bằng cách khởi tạo các đối tượng bên trong phần khai báo mảng:

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

Các phương pháp tiếp cận khác được đề xuất đều có giá trị như nhau, nhưng nếu bạn chỉ đơn giản là cố gắng đưa vào một mảng mà không khai báo bất kỳ biến nào, Swift làm cho dễ dàng.

+1

Lớp học sinh nằm ngoài tầm kiểm soát của tôi và tôi không thể chỉnh sửa nó. Nó nằm trong một khung công tác khác. Vì vậy, tôi chỉ có thể kế thừa hoặc mở rộng nó. – TruMan1

1

Tôi chỉ muốn chỉ ra rằng nếu cấu trúc của bạn có thể không thay đổi, bạn chỉ có thể sử dụng một struct chứ không phải là một class và bạn sẽ nhận được một initializer ngầm miễn phí:

Chỉ cần dán vào một sân chơi và thay đổi struct thành class và bạn sẽ thấy ý tôi là gì.

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

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

Ah hah thật tuyệt !! Đã không nhận ra cấu trúc này có nhưng không phải loại khác. Tốt để biết !! Chỉ có điều là lớp Sinh viên nằm ngoài tầm kiểm soát của tôi bị chôn vùi trong một thư viện khác nên tôi không thể sửa đổi nguồn của nó. – TruMan1

1

Đây chỉ là cú pháp kẹo nhưng tôi sử dụng một nhà điều hành tùy chỉnh để làm điều này loại điều:

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() } 
    ] 
Các vấn đề liên quan