Swifterino
Swifterino

Reputation: 91

Swift Objects initialization (Class factory method, default init, convenience init)

I'm trying to figure out the best pattern to work with objects in Swift.

i think i got it right with the initializers, both convenience and default... but what happen with the class factory methods?

I tried to create a simple class Person and a subclass Student, with few properties and methods. is it the most correct way to do it?

   class Person{
    
    var _name: String
    var _surname: String
    var _dateOfBirthday: String
    var _phoneNumb: [String]
    
    init(name:String, surname:String, dateOfBirthday:String, phone:[String]){
        self._name = name
        self._surname = surname
        self._dateOfBirthday = dateOfBirthday
        self._phoneNumb = phone
    }
    
    convenience init() {
        self.init(name:"",surname:"",dateOfBirthday:"", phone:[])
    }
    
    convenience init(name:String){
        self.init(name:name,surname:"",dateOfBirthday:"", phone:[])
    }
    
    
}



class Student:Person{
    
    var _studentId:Int
    
    init(name: String, surname: String, dateOfBirthday: String, phone: [String], id:Int) {
        self._studentId = id
        super.init(name: "", surname: "", dateOfBirthday: "", phone: [])
    }
    
    convenience init(){
        self.init(name: "", surname: "", dateOfBirthday: "", phone: [], id:0)
    }
    
    convenience init(name:String){
        self.init(name:name,surname:"",dateOfBirthday:"", phone:[], id:0)
    }
    
}

what if i want to add a class factory method? would it be something like this or i'm doing it wrong?

class func Person() -> Person {
 var x = Person()
 x._telephoneNumber = [String]() // is this needed? or i can initialize it later?
 return x
}

class func PersonWithName(name:String) -> Person {
 var x = Person(name:name, surname:"", dateOfBirthday:"", telephoneNumber:[])
 return x
}

is this correct? why would it be better to use the init instead of the class factory?

Upvotes: 5

Views: 13651

Answers (2)

tng
tng

Reputation: 4336

Prior to the recent Xcode 6.1 and Swift 1.1, it was necessary to use factory pattern if construction could fail because init() could not return optionals. This was also why many cocoa/objective-c libraries imported had factory methods.

With the release of Xcode 6.1 and Swift 1.1 and the support for init() that can return optionals, you should use the init() pattern with convenience initializers. With this release, Apple also changed their cocoa/objective-c imports to use the init() -> T? pattern over the factory method.

See https://developer.apple.com/library/ios/releasenotes/DeveloperTools/RN-Xcode/Chapters/xc6_release_notes.html for the release notes.

Upvotes: 0

radex
radex

Reputation: 6536

is this correct? why would it be better to use the init instead of the class factory?

Why would you create a "class factory" if you can use init? init is idiomatic Swift way of creating new objects of a class.

Adding convenience initializers is the right choice in most cases when you want to add a shortcut to class's main (designated) initializer. However, in your case, they are completely unnecessary, because Swift supports default argument values.

Just define your initializer like so:

init(name:String = "", surname:String = "", dateOfBirthday:String = "", phone:[String] = []) { ... }

This way, you can invoke it as Person() or Person(name: "Andrew") or with any other combination of arguments.

EDIT:

As a side note, prefixing instance variables with an underscore generally doesn't seem to be idiomatic Swift. It's okay to omit the underscore and use self. to disambiguate between local and instance variables:

self.name = name
self.surname = surname
self.dateOfBirthday = dateOfBirthday
self.phoneNumb = phone

Upvotes: 5

Related Questions