In my experience, it has often been the case that one would like to access a private member of a class or structure from within an extension to that type declared in a separate file. The only way to achieve this would be to weaken the member's access level to at least internal, thereby, however, also exposing it to code outside that class or structure.
For example, let's say I have some kind of structure looking like this:
// DataProvider.swift
struct DataProvider {
func data() throws -> Data {
return try Data(contentsOf: self.fileURL)
}
private var fileURL: URL {
return URL(fileURLWithPath: "/some/directory/\(self.dataID)"
}
let dataID: Int
}
Now, let's say, in another file, I want to extend this structure:
// DataProvider+modificationDate.swift
extension DataProvider {
func modificationDate() throws -> Date? {
let attributes = try FileManager.default.attributesOfItem(atPath: self.fileURL.path)
return attributes[FileAttributeKey.modificationDate] as? Date
}
}
Of course, without moving the extension to the same source file, I cannot access the fileURL
property. So, the only way to access it, would be to make it internally accessible:
struct DataProvider {
var fileURL: URL { … }
…
}
This, however, would also expose it to code outside the structure, which is what I may be trying to avoid.
The solution would be to, in addition to fileprivate
, introduce a new access level, say typeprivate
, that restricts access to the declaring type and any extensions to that type:
struct DataProvider {
typeprivate fileURL: URL { … }
…
}
Of course, one might argue that this mechanism could be abused to expose "type-private" members:
extension DataProvider {
public var publicFileURL: URL {
return self.fileURL
}
}
But this would have just as well been possible if the member had been declared internal.
What do you think?