Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

One-step object creation and property initialization in Swift?

Is there a way to assign property values to a class instance even if it is not a parameter in the init constructor? For example, in C# I can do this:

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

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

Notice for student2 I can still assign values during initialization even though there's no constructor in the class.

I could not find in the documentation if you can do something like this for Swift. If not, is there a way to use extensions to extend the Student class to assign property values during initialization?

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, like this:

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

Any native or elegant way to achieve this in Swift?

like image 364
TruMan1 Avatar asked Jan 22 '16 22:01

TruMan1


People also ask

How do you initialize an object in Swift?

An initializer is a special type of function that is used to create an object of a class or struct. In Swift, we use the init() method to create an initializer. For example, class Wall { ... // create an initializer init() { // perform initialization ... } }

What is Swift initialization?

Swift init() Initialization is the process of preparing an instance of a class, structure, or enumeration for use. This process involves setting an initial value for each stored property on that instance and performing any other setup or initialization that is required before the new instance is ready for use.

What is super init () Swift?

The init() initializer for Bicycle starts by calling super. init(), which calls the default initializer for the Bicycle class's superclass, Vehicle. This ensures that the numberOfWheels inherited property is initialized by Vehicle before Bicycle has the opportunity to modify the property.


2 Answers

You have a couple of options depending on how you want to configure this type and what syntax is most convenient for you.

You could define a convenient initializer which accepts the properties you want to set. Useful if you're setting the same properties all the time, less useful if you're setting an inconsistent set of optional properties.

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

You could define a convenience initializer which accepts a block to configure the new instance.

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

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

You could imitate Ruby's tap method as an extension so you can operate on an object in the middle of a method chain.

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

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

If that last one is useful you might want to be able to adopt tap on any object. I don't think you can do that automatically but you can define a default implementation to make it easier:

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"})
like image 98
Jonah Avatar answered Sep 21 '22 03:09

Jonah


If your class has no required initialiser, you can use a closure method to set the Student properties before returning the new Student object as follow:

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
like image 41
Leo Dabus Avatar answered Sep 25 '22 03:09

Leo Dabus