Separating interface from its implementation

I want to split my information elements, but it is not possible.

For example, neither this (in single file):

// Foo.swift
//
class Foo {
    var x : Int;
    
    init ();
    init (v: Int);
    
    func bar () -> Int;
    func bar (u:Int, v:Int) -> Int;
}

extension Foo {
    init () {
        ...
    }
    
    init (v: Int) {
        ...
    }
}

extension Foo {
    func bar () -> Int {
        ...
    }
    
    func bar (u:Int, v:Int) -> Int {
        ...
    }
}

Nor this (in multiple files):

// Foo.swift
//
class Foo {
    var x : Int;
    
    init ();
    init (v: Int);
    
    func bar () -> Int;
    func bar (u:Int, v:Int) -> Int;
}

// Foo-init.swift
//
extension Foo {
    init () {
        ...
    }
    
    init (v: Int) {
        ...
    }
}

// Foo-bar.swift
//
extension Foo {
    func bar () -> Int {
        ...
    }
    
    func bar (u:Int, v:Int) -> Int {
        ...
    }
}

Is there any reason for why this is not possible?

I guess, based on the code you posted, that you are trying to “forward-declare” your init and bar methods.

There are no forward declarations in Swift.

Because Foo is a class, it can have two kinds of init: “designated” and “convenience”. All designated inits need to be defined in the main body of Foo, and you must have at least one designated init. You can put convenience inits and other methods in extensions. For example:

class Foo {
    var x: Int
    
    // Note that this is a designated init because it doesn't have the
    // `convenience` keyword.
    init() {
        x = 0
    }
}

extension Foo {
    convenience init(v: Int) {
        self.init()
        x = v
    }
}

extension Foo {
    func bar() -> Int {
        return x
    }
    
    func bar(u:Int, v:Int) -> Int {
        return x + u + v
    }
}
2 Likes

Thank you for explaining the distinction between designated and convenience intialisers.

My intention is simply to present all the key information in a manner which makes it easier to digest, without showing any implementation details.

// Foo.swift
//
class Foo {
    var x : Int;
    
    init ();
    init (v: Int);
    
    func bar () -> Int;
    func bar (u:Int, v:Int) -> Int;
}

Is there a technical reason that this can't be done in Swift?

It is kind of sad that this is not possible today in Swift, a modern programming language.

If you're using Xcode, open the assistant pane (control + option + command + enter) and select "generated interface" up top

1 Like

That seems like a job for the text editor/IDE level. It's also duplicating information, so you have to jump back and forth to keep it all in sync. Why waste human effort to generate interfaces for presentation like this, when a machine can prepare it automatically?

Ironically, the split header+implementation structure of C/C++ programs is often cited as one of the biggest factors that make them feel "old".

1 Like