2016-01-22 2 views
6

Есть ли способ присвоить значения свойства экземпляру класса, даже если он не является параметром в конструкторе init? Например, в C# я могу это сделать:Создание одноэтапного объекта и инициализация свойств в Swift?

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

Любой родной или элегантный способ для достижения это в Свифт?

ответ

8

У вас есть несколько вариантов в зависимости от того, как вы хотите настроить этот тип и какой синтаксис наиболее удобен для вас.

Вы можете определить удобный инициализатор, который принимает свойства, которые вы хотите установить. Полезно, если вы постоянно устанавливаете одни и те же свойства, менее полезно, если вы устанавливаете непоследовательный набор дополнительных свойств.

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

Вы можете имитировать метод Руби 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"}) 
+0

Это гениально! – TruMan1

4

Если ваш класс не имеет необходимый Инициализатора, вы можете использовать метод закрытия, чтобы установить свойство 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 
1

Причина Я ищу это так, я могу добавить кучу экземпляров в [.] массив без явного создания переменных для каждого экземпляра студент

Я не знаком с C#, но в Swift, вы можете сделать это просто инициализирует объекты внутри объявления массива:

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

Другие предложенные подходы являются одинаково действительными, но если вы просто пытаетесь заполнить массив без объявления каких-либо переменных, Swift делает это легко.

+1

Класс ученика из-под контроля, и я не могу его отредактировать. Он находится в другой структуре. Поэтому я могу только наследовать или расширять его. – TruMan1

1

Я просто хотел бы отметить, что, если ваша структура может быть неизменна, вы можете просто использовать struct, а не class, и вы получите неявный инициализатору бесплатно:

Просто вставьте в игровую площадку и измените структуру на класс, и вы поймете, что я имею в виду.

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

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

Ах, это здорово! Не понимал, что у структур есть это, но не другие типы. Хорошо знать!! Единственное, что класс ученика находится вне моего контроля, похоронен в другой библиотеке, поэтому я не могу изменить его источник. – TruMan1

1

Это просто синтаксический леденец, но я использую пользовательский оператор, чтобы сделать такую ​​вещь:

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() } 
    ] 
Смежные вопросы