6

I am building a large class in Swift, which I want to spread over multiple files, since it is getting too big to effectively work in. It cannot be subclassed, since it is just a class with many functions. (I might be able to optimise it later on and remove double code, but I still want to achieve this.)

To make it easier to work in I want to spread the class into multiple Swift-files, using Extensions. I already achieved it partly; extending the base-class by creating the extensions in the same file. This works without any problems.

Lets say the base-file is BaseClass.Swift (and the class BaseClass) and I want to extend it to BaseClassExtension.swift, I put the following in BaseClassExtension.swift:

extension BaseClass {
    func doStuff() -> String {
        return myVariable
    }
}

In BaseClass.swift I have private var myVariable = "I am a string", but in BaseClassExtension.swift I get the following error: Use of unresolved identifier 'myVariable'

I have tried the following things:

  • Make the Extension public
  • Make the BaseClass public
  • Make both public
  • (And by default they were both default (internal I guess?))

When I remove private from myVariable, the error is solved, but I really want it to be private, since it may never be accessed from outside the class directly.

Jeroen
  • 2,011
  • 2
  • 26
  • 50
  • What happens if you change `extension BaseClass` to `extension BaseClassExtension: BaseClass`? – JAL Nov 19 '15 at 18:11
  • Then I get the following error: `Use of undeclared type 'BaseClassExtension'`. Which I think makes sense, since you cannot extend a not-existing class. But it would not have been a good solution. – Jeroen Nov 19 '15 at 18:18
  • 1
    Never mind, I was confused. You are correct. – JAL Nov 19 '15 at 18:26
  • The idea of using the Swift extension facility to somewhat replicate the C# "partial class" facility becomes very problematic if derived classes are going to be created, and they should also preferably be split up into multiple source files. The problem is that methods in extensions can not override each other. See here, for example: http://stackoverflow.com/questions/38213286/overriding-methods-in-swift-extensions – RenniePet Jan 24 '17 at 23:16

1 Answers1

7

You have to make the extension in the same file as your class, since private is only scoped to the this file.

However you could do something like this:

private(set) myVariable: String

So the getter can be accessed from your extension but (at least) the setter remains hidden to this scope.

Qbyte
  • 12,753
  • 4
  • 41
  • 57
  • Thanks for your answer, but the whole reason I want to use extensions is so that I can put it in different files. But if that is not possible, is there another solution to split my class up in multiple files, while I can keep the variables private? – Jeroen Nov 20 '15 at 08:55
  • 5
    @JeroenJK There is no way to access them outside the source file. As the Swift books says: "Private access restricts the use of an entity to its own defining source file. Use private access to hide the implementation details of a specific piece of functionality.". Imagine if this would be possible, you could access internal variables of Arrays and Strings only with the use of extensions which should never be accessed. – Qbyte Nov 21 '15 at 00:59
  • I now see why you are right. I will use this approach. – Jeroen Nov 22 '15 at 16:57