gepree
gepree

Reputation: 677

Swift 4: Simplifying constructor that just sets fields from parameters?

The following Swift 4 class sets 7 fields from the 7 parameters passed into the constructor.

Seeing as the only job of this constructor is to assign each of these parameters to the fields, one by one, is there any simpler way of writing the code? There appears to be a huge amount of duplication for no real benefit.

public class FactoryForListOfKnownApp {
    private let readerForVersion: ReaderForVersion
    private let finderForNameOfApp: FinderForNameOfApp
    private let listOfAppName: [AppName]
    private let factoryForVersionFromVersion: FactoryForVersionFromVersion
    private let finderForAppData: FinderForAppData
    private let finderForWebPage: FinderForWebPage
    private let factoryForBuilderForKnownApp: FactoryForBuilderForKnownApp

    public
    init(withReaderForVersion readerForVersion: ReaderForVersion,
         andFinderForNameOfApp finderForNameOfApp: FinderForNameOfApp,
         andListOfAppName listOfAppName: [AppName],
         andFactoryForVersionFromVersion factoryForVersionFromVersion: FactoryForVersionFromVersion,
         andFinderForAppData finderForAppData: FinderForAppData,
         andFinderForWebPage finderForWebPage: FinderForWebPage,
         andFactoryForBuilderForKnownApp factoryForBuilderForKnownApp: FactoryForBuilderForKnownApp) {
        self.readerForVersion = readerForVersion
        self.finderForNameOfApp = finderForNameOfApp
        self.listOfAppName = listOfAppName
        self.factoryForVersionFromVersion = factoryForVersionFromVersion
        self.finderForAppData = finderForAppData
        self.finderForWebPage = finderForWebPage
        self.factoryForBuilderForKnownApp = factoryForBuilderForKnownApp
    }

    public func findAppData(withName name: String) -> AppData {
        return finderForAppData.findAppData(called: name)
    }

    // ...
}

Are there any alternatives to writing code like this?

Or are there any Swift proposals for an alternative way of writing such a class?

For example, something like this using a new annotation @Init:

public
class FactoryForListOfKnownApp {
    @Init
    private let readerForVersion: ReaderForVersion

    @Init
    private let finderForNameOfApp: FinderForNameOfApp

    @Init
    private let listOfAppName: [AppName]

    @Init
    private let factoryForVersionFromVersion: FactoryForVersionFromVersion

    @Init
    private let finderForAppData: FinderForAppData

    @Init
    private let finderForWebPage: FinderForWebPage

    @Init
    private let factoryForBuilderForKnownApp: FactoryForBuilderForKnownApp

    public func findAppData(withName name: String) -> AppData {
        return finderForAppData.findAppData(called: name)
    }

    // ...
}

Many thanks

Upvotes: 4

Views: 563

Answers (1)

Ole Begemann
Ole Begemann

Reputation: 135578

For classes, there is no better alternative, no. (Leaving aside for the moment code generation with an external tool such as Sourcery). Only structs get a default memberwise initializer.

There was a Swift-Evolution proposal in early 2016 for more flexible memberwise initializers (including for classes). As far as I recall, the consensus in the community was that the proposal was generally the right idea, but at the time it was deferred because other tasks had higher priorities.

It hasn't been revisited since and I don't see any chance of it being accepted in the Swift 5 timeframe (i.e. before September 2018). After that, who knows. Something like it will probably eventually come.

Upvotes: 2

Related Questions