Swift make func in extension "private" in same extension - swift

Is there a way to make the extension able to access private var defined in the definition file, but keep the extension's private function private to that extension only (not assessable in definition file)?
For example:
class MyClass {
private var myStr = "str"
func doSomething() {
funcA() // <- should cause compiler error
}
}
extension MyClass {
private func funcA() {
print(myStr)
}
}
So doSomething() can not call funcA(), but funcA() can access myStr.

Yes. Put the definition in one file, and the extension in another.
Private access restricts the use of an entity to the enclosing
declaration, and to extensions of that declaration that are in the
same file.
That information is not quite complete. As you've seen, anything private in an extension is accessible in the declaration, and other extensions. But only in the same file.
https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html

Related

What's the difference of `private` and `fileprivate` class in the same file in Swift? [duplicate]

This question already has an answer here:
In Swift 3, is there a difference between 'private class Foo' and 'fileprivate class Foo' in regards to member variables?
(1 answer)
Closed 2 years ago.
As the sample code here, what's the difference of private and fileprivate class in the same file in Swift?
// ViewController.swift
private class A {
var name: String = ""
let d = B.D()
}
fileprivate class B {
var name: String = ""
private let c = C()
private class C {
var number: String = ""
}
fileprivate let d = D()
fileprivate class D {
var number: String = ""
}
}
Since class A and B are in the sample file, A can't be any more private then B, right?
Sorry this is a very picky question, but I just want to confirm it.
Access modifiers in swift have been charged a few times during the past few releases.
For now, let me suggest a code sample instead of explanation first:
All code in one file:
fileprivate class Foo {
private var someVariablePrivate: Int?
fileprivate var someVariableFileprivate: Int?
private func makeBar() { }
fileprivate func makeFoo() { }
}
extension Foo {
func bar() {
let value = someVariablePrivate // OK
let value2 = someVariableFileprivate // OK
}
}
private class Foofoo: Foo {
override func makeFoo() {
// OK
}
override func makeBar() {
// NOK, because private
}
}
class Bar {
func foo() {
let object = Foo()
let value = object.someVariableFileprivate // OK
let value2 = object.someVariablePrivate // NOK - because it private to that class
}
}
Previously, private restrict access only to type definition, but within few lates version of Swift, it has been modified and updated, so even extension of same type can use private variables
As Apple mention:
File-private access restricts the use of an entity to its own defining
source file. Use file-private access to hide the implementation
details of a specific piece of functionality when those details are
used within an entire file.
Private access restricts the use of an entity to the enclosing
declaration, and to extensions of that declaration that are in the
same file. Use private access to hide the implementation details of a
specific piece of functionality when those details are used only
within a single declaration.
we could compare a bit this modifiers:
why do we ned both of them:
You may, however, want to mark some parts of your code as file private
or private in order to hide their implementation details from other
code within the app’s module.
When to use fileprivate
Although the keywords are almost the same, there is a clear difference in their use cases. Fileprivate access restricts the use of an entity within the same defined source file. The only reason you would use fileprivate is when you want to access your code within the same file from different classes or structs.
When to use private
The private keyword is used a lot more and restricts the use of an entity to the enclosing declaration and its extensions. The extensions, however, have to be defined within the same file. In other words, private declarations will not be visible outside the file. You can use this keyword to only expose the minimal code needed to interact with the entity. This will improve readability and makes it easier to use and understand your code for others.
your question: Since class A and B are in the sample file, A can't be any more private then B, right?
In case of class A with private access specifier it won't be accessible outside it's declared scope.
In case of class B it will be accessible to the class A but it's private properties won't be accessible in class A
For more information, you can refer to this interesting article:
https://www.avanderlee.com/swift/fileprivate-private-differences-explained/#when-to-use-private

Private qualifier to an extension produces fileprivate behavior

Person.swift
class Person {
var name: String
init(name: String){
self.name = name
}
func greet() {
print("Hello, I am \(name)")
}
}
Workplace.swift
class WorkPlace {
var employees: [Person]
init(employees: [Person]) {
self.employees = employees
}
func greet() {
for employee in employees {
employee.customGreeting()
}
}
}
private extension Person {
func customGreeting() {
print("Hi")
}
}
Here I have a simple class called Person defined in Person.swift and a Workplace class defined in Workplace.swift.
The following is an excerpt taken from the Swift language guide (Access Control)
Alternatively, you can mark an extension with an explicit access-level modifier (for example, private) to set a new default access level for all members defined within the extension.
According to this I would expect the method customGreeting in the private extension of Place not be visible inside Person.swift as it would be a private method and it is defined in a different file than the one the class is declared in, which is exactly what happens. I would also expect that method to not be visible inside Workplace.swift but it does. I am able to compile this code without any errors.
If I mark the method as private explicitly then it is not visible inside Workplace.swift. Shouldn't specifying the extension as private be enough to make the method private like it says in the language guide?
private extension Person {
private func customGreeting() {
print("Hi")
}
}
I know that this is a contrived example and I am just trying to get a clear picture of how access control works in swift.
The issue isn't that methods declared in a private extension available in other classes, but rather, more narrowly, that private qualifier to an extension produces fileprivate behavior.
This is explicitly acknowledged in SE-0025, which says:
As before, an extension with an explicit access modifier overrides the default internal access by specifying a default scope. Therefore, within an extension marked private, the default access level is fileprivate (since extensions are always declared at file scope). This matches the behavior of types declared private at file scope.
This seems inconsistent with their broader statement:
... you can mark an extension with an explicit access-level modifier (for example, private) to set a new default access level for all members defined within the extension. This new default can still be overridden within the extension for individual type members.
While there is an inconsistency here, it would appear to be a conscious decision.

What is the difference between private and fileprivate in Swift 4

In Swift 4, since now private is visible in extensions also in the same source code file, how is it different from the fileprivate access modifier?
Background: In Swift 3, private variables in a class are not visible in its extensions in the same file. For that, fileprivate had to be used.
File Private
File-private access restricts the use of an entity to its own defining source file. Use file-private access to hide the implementation details of a specific piece of functionality when those details are used within an entire file.
Syntax: fileprivate <var type> <variable name>
Example: fileprivate class SomeFilePrivateClass {}
Private
Private access restricts the use of an entity to the enclosing declaration, and to extensions of that declaration that are in the same file. Use private access to hide the implementation details of a specific piece of functionality when those details are used only within a single declaration.
Syntax: private <var type> <variable name>
Example: private class SomePrivateClass {}
Here is more detail about all access levels: Swift - Access Levels
Answer to your question:
(In Swift 3, private variables in a class are not visible in its extensions in the same file. For that, fileprivate had to be used.)
Yes, in Swift 4.0, Private is now accessible in extension but within same file. If you declare/define extension in other file, then your private variable will not be accessible to your extension
Look at this images:
File: ViewController.swift
Here extension and view controller both are in same file, hence private variable testPrivateAccessLevel is accessible in extension
File: TestFile.swift
Here extension and view controller both are in different files, hence private variable testPrivateAccessLevel is not accessible in extension.
Here class ViewController2 is a subclass of ViewController and both are in same file. Here private variable testPrivateAccessLevel is not accessible in Subclass but fileprivate is accessible in subclass.
Applicable in swift 4.0 and its versions
Private
Private access only in class and its extension(When extension is in the same .swift file).
File Private
File-private access only in class and its extension & subClass(When extension or subClass is in the same .swift file).
///////////////ViewController1.swift file
class ViewController1 {
private func testPrivate() {
print("testPrivate")
}
fileprivate func testFilePrivate() {
print("testFilePrivate")
}
func doesNothing1() {
testPrivate() //success
testFilePrivate() //success
}
}
extension ViewController1 {
func doesNothingInExtensionSameFile() {
testPrivate() //success
testFilePrivate() //success
}
}
class SomeOtherClassInSameFile {
let vc1 = ViewController1()
func doesNothing() {
vc1.testPrivate() //throws error
vc1.testFilePrivate() //success
}
}
////////////// ViewController2.swift file
extension ViewController1 {
func doesNothingInExtensionDifferentFile() {
testPrivate() //throws error
testFilePrivate() //throws error
}
}
private and fileprivate access levels have come closer with Swift4.
The difference in access lies as follows:
fileprivate members - only & entirely within that .swift file
private members - only in that class & extension of the class if both are present in same .swift file
Hence only fileprivate members(not private) can be accessed in
Sub Classes in the same .swift file
Instances of the class (initialized in another class) in the same .swift file.
Open Vs Public:
Public does not allow a class to be inherited in another
module/target whereas Open does.
Public method does not allow to be overridden in subclass in another
module/target whereas Open does.
Apart from above both are same.
Private Vs Fileprivate:
(Within single file) Private does not allow to access (func and properties) in subclass whereas FilePrivate does.
(Outside File) Private and FilePrivate both can't be accessible.
Apart from above both are same.
"Private" is accessible only in class, "FilePrivate" accessible only in .swift file.
Private : Access in Class and Class Extension.
FilePrivate : Access in class, subClass, Extension,

What is a good example to differentiate between fileprivate and private in Swift3

This article has been helpful in understanding the new access specifiers in Swift 3. It also gives some examples of different usages of fileprivate and private.
My question is - isn't using fileprivate on a function that is going to be used only in this file the same as using private?
fileprivate is now what private used to be in earlier
Swift releases: accessible from
the same source file. A declaration marked as private can now only be accessed within the lexical scope it is declared in.
So private is more restrictive than fileprivate.
As of Swift 4, private declarations inside a type are accessible to extensions of the same type if the extension is defined in the same source file.
Example (all in one source file):
class A {
private func foo() {}
fileprivate func bar() {}
func baz() {
foo()
bar()
}
}
extension A {
func test() {
foo() // Swift 3: error: use of unresolved identifier 'foo'
// Swift 4: no error because extension is in same source file
bar()
}
}
let a = A()
a.foo() // error: 'foo' is inaccessible due to 'private' protection level
a.bar()
The private foo method is accessible only within the scope of
the class A { ... } definition. It is not even accessible from
an extension to the type (in Swift 3, see the second note below for
changes in Swift 4).
The file-private bar method is accessible from the same source file.
Notes:
The proposal SE-0159 – Fix Private Access Levels suggested to revert to the Swift 2 semantics in Swift 4. After a lengthy and controversial discussion on the swift-evolution mailing list, the proposal was rejected.
The proposal SE-0169 – Improve Interaction Between private Declarations and Extensions suggests to make private
declarations inside a type accessible to extensions of the same type
if the extension is defined in the same source file.
This proposal was accepted and implemented in Swift 4.
I just draw a diagram about private, fileprivate, open and public
Hope it can quickly help you , for text description please refer to Martin R 's answer
[ Update Swift 4, 5 ]
Updated for Swift 5
Private vs FilePrivate
For better clarity paste the code snippet in Playground
class Sum1 {
let a: Int!
let b: Int!
private var result: Int?
fileprivate var resultt: Int?
init(a : Int, b: Int) {
self.a = a
self.b = b
}
func sum(){
result = a + b
print(result as! Int)
}
}
let aObj = Sum1.init(a: 10, b: 20)
aObj.sum()
aObj.resultt //File Private Accessible as inside same swift file
aObj.result //Private varaible will not be accessible outside its definition except extensions
extension Sum1{
func testing() {
// Both private and fileprivate accessible in extensions
print(result)
print(resultt)
}
}
//If SUM2 class is created in same file as Sum1 ---
class Sum2{
func test(){
let aSum1 = Sum1.init(a: 2, b: 2)
// Only file private accessible
aSum1.resultt
}
}
Note: Outside of Swift file both private and fileprivate are not accessible.
A practical rule of thumb is that you use private for variables, constants, inner structs and classes that are used only inside the declaration of your class / struct. You use fileprivate for things that are used inside of your extensions within the same file as your class/struct but outside of their defining curly braces (ie. their lexical scope).
class ViewController: UIViewController {
#IBOutlet var tableView: UITableView!
//This is not used outside of class Viewcontroller
private var titleText = "Demo"
//This gets used in the extension
fileprivate var list = [String]()
override func viewDidLoad() {
navigationItem.title = titleText
}
}
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return list.count
}
}
In Swift 4.0, Private is now accessible in extension but within same file. If you declare/define extension in other file, then your private variable will not be accessible to your extension**
File Private
File-private access restricts the use of an entity to its own defining source file. Use file-private access to hide the implementation details of a specific piece of functionality when those details are used within an entire file.
Syntax: fileprivate <var type> <variable name>
Example: fileprivate class SomeFilePrivateClass {}
Private
Private access restricts the use of an entity to the enclosing declaration, and to extensions of that declaration that are in the same file. Use private access to hide the implementation details of a specific piece of functionality when those details are used only within a single declaration.
Syntax: private <var type> <variable name>
Example: private class SomePrivateClass {}
Here is more detail about all access levels: Swift - Access Levels
Look at this images:
File: ViewController.swift
Here extension and view controller both are in same file, hence private variable testPrivateAccessLevel is accessible in extension
File: TestFile.swift
Here extension and view controller both are in different files, hence private variable testPrivateAccessLevel is not accessible in extension.
Here class ViewController2 is a subclass of ViewController and both are in same file. Here private variable testPrivateAccessLevel is not accessible in Subclass but fileprivate is accessible in subclass.
Although #MartinR's and #StephenChen's answer are perfect, Swift 4 changes things a little bit.
Private is now considered as private to a class in which it is declared and also to its extensions.
FilePrivate is considered to be private in that file be it a class in which the variable is defined, it's extension, or any other classes defined in that same file.
filePrivate - access controll level is within the file.
case 1: If we create extension with in same class file and try to access fileprivate function or fileprivate property in its extension - access allowed
case 2: If we create a extension of class in new file - And now try to access fileprivate function or fileprivate property - access not allowed
private - access control level is with in lexical scope
case 1: If property or function is declared as private in class - then scope is by default the class.
case 2: if private instance is declared with in function body - then scope of instance is limited to function body.
This is the explanation for swift 4. For swift 3, the difference is the private. swift 3 private cannot be accessed by its extension, only Class A itself can access.
After swift 4, fileprivate becomes a bit redundant, because person normally will not define the subclass in the same file. Private should be enough for most cases.
In the following example, language constructs modified by private and fileprivate seem to behave identically:
fileprivate func fact(_ n: Int) -> Int {
if (n == 0) {
return 1
} else {
return n * fact(n - 1)
}
}
private func gauss(_ n: Int) -> Int {
if (n == 0) {
return 0
} else {
return n + gauss(n - 1)
}
}
print(fact(0))
print(fact(5))
print(fact(3))
print(gauss(10))
print(gauss(9))
This is according to intuition, I guess. But, is there any exception?
Kindest regards.
class Privacy {
fileprivate(set) var pu:Int {
get {
return self.pr
}
set {
self.pr = newValue
}
}
private var pr:Int = 0
fileprivate var fp:Int = 0
func ex() {
print("\(self.pu) == \(self.pr) and not \(self.fp)")
}
}
extension Privacy {
func ex2() {
self.pu = 5
self.ex()
}
}
I like this because it is super simple for ivars.
Try changing fileprivate to private (and vice versa) and see what happens on compile...

Overriding methods in Swift extensions

I tend to only put the necessities (stored properties, initializers) into my class definitions and move everything else into their own extension, kind of like an extension per logical block that I would group with // MARK: as well.
For a UIView subclass for example, I would end up with an extension for layout-related stuff, one for subscribing and handling events and so forth. In these extensions, I inevitably have to override some UIKit methods, e.g. layoutSubviews. I never noticed any issues with this approach -- until today.
Take this class hierarchy for example:
public class C: NSObject {
public func method() { print("C") }
}
public class B: C {
}
extension B {
override public func method() { print("B") }
}
public class A: B {
}
extension A {
override public func method() { print("A") }
}
(A() as A).method()
(A() as B).method()
(A() as C).method()
The output is A B C. That makes little sense to me. I read about Protocol Extensions being statically dispatched, but this ain't a protocol. This is a regular class, and I expect method calls to be dynamically dispatched at runtime. Clearly the call on C should at least be dynamically dispatched and produce C?
If I remove the inheritance from NSObject and make C a root class, the compiler complains saying declarations in extensions cannot override yet, which I read about already. But how does having NSObject as a root class change things?
Moving both overrides into their class declaration produces A A A as expected, moving only B's produces A B B, moving only A's produces C B C, the last of which makes absolutely no sense to me: not even the one statically typed to A produces the A-output any more!
Adding the dynamic keyword to the definition or an override does seem to give me the desired behavior 'from that point in the class hierarchy downwards'...
Let's change our example to something a little less constructed, what actually made me post this question:
public class B: UIView {
}
extension B {
override public func layoutSubviews() { print("B") }
}
public class A: B {
}
extension A {
override public func layoutSubviews() { print("A") }
}
(A() as A).layoutSubviews()
(A() as B).layoutSubviews()
(A() as UIView).layoutSubviews()
We now get A B A. Here I cannot make UIView's layoutSubviews dynamic by any means.
Moving both overrides into their class declaration gets us A A A again, only A's or only B's still gets us A B A. dynamic again solves my problems.
In theory I could add dynamic to all overrides I ever do but I feel like I'm doing something else wrong here.
Is it really wrong to use extensions for grouping code like I do?
Extensions cannot/should not override.
It is not possible to override functionality (like properties or methods) in extensions as documented in Apple's Swift Guide.
Extensions can add new functionality to a type, but they cannot override existing functionality.
Swift Developer Guide
The compiler is allowing you to override in the extension for compatibility with Objective-C. But it's actually violating the language directive.
😊That just reminded me of Isaac Asimov's "Three Laws of Robotics" 🤖
Extensions (syntactic sugar) define independent methods that receive their own arguments. The function that is called for i.e. layoutSubviews depends on the context the compiler knows about when the code is compiled. UIView inherits from UIResponder which inherits from NSObject so the override in the extension is permitted but should not be.
So there's nothing wrong with grouping but you should override in the class not in the extension.
Directive Notes
You can only override a superclass method i.e. load() initialize()in an extension of a subclass if the method is Objective-C compatible.
Therefore we can take a look at why it is allowing you to compile using layoutSubviews.
All Swift apps execute inside the Objective-C runtime except for when using pure Swift-only frameworks which allow for a Swift-only runtime.
As we found out the Objective-C runtime generally calls two class main methods load() and initialize() automatically when initializing classes in your app’s processes.
Regarding the dynamic modifier
From the Apple Developer Library (archive.org)
You can use the dynamic modifier to require that access to members be dynamically dispatched through the Objective-C runtime.
When Swift APIs are imported by the Objective-C runtime, there are no guarantees of dynamic dispatch for properties, methods, subscripts, or initializers. The Swift compiler may still devirtualize or inline member access to optimize the performance of your code, bypassing the Objective-C runtime. 😳
So dynamic can be applied to your layoutSubviews -> UIView Class since it’s represented by Objective-C and access to that member is always used using the Objective-C runtime.
That's why the compiler allowing you to use override and dynamic.
One of the goals of Swift is static dispatching, or rather the reduction of dynamic dispatching. Obj-C however is a very dynamic language. The situation you're seeing is borne out of the link between the 2 languages and the way they work together. It shouldn't really compile.
One of the main points about extensions is that they are for extending, not for replacing / overriding. It's clear from both the name and the documentation that this is the intention. Indeed if you take out the link to Obj-C from your code (remove NSObject as the superclass) it won't compile.
So, the compiler is trying to decide what it can statically dispatch and what it has to dynamically dispatch, and it's falling through a gap because of the Obj-C link in your code. The reason dynamic 'works' is because it's forcing Obj-C linking on everything so it's all always dynamic.
So, it isn't wrong to use extensions for grouping, that's great, but it is wrong to override in extensions. Any overrides should be in the main class itself, and call out to extension points.
There is a way to achieve a clean separation of class signature and implementation (in extensions) while maintaining the ability to have overrides in subclasses. The trick is to use variables in place of the functions
If you make sure to define each subclass in a separate swift source file, you can use computed variables for the overrides while keeping the corresponding implementation cleanly organized in extensions. This will circumvent Swift's "rules" and will make your class's API/signature neatly organized in one place:
// ---------- BaseClass.swift -------------
public class BaseClass
{
public var method1:(Int) -> String { return doMethod1 }
public init() {}
}
// the extension could also be in a separate file
extension BaseClass
{
private func doMethod1(param:Int) -> String { return "BaseClass \(param)" }
}
...
// ---------- ClassA.swift ----------
public class A:BaseClass
{
override public var method1:(Int) -> String { return doMethod1 }
}
// this extension can be in a separate file but not in the same
// file as the BaseClass extension that defines its doMethod1 implementation
extension A
{
private func doMethod1(param:Int) -> String
{
return "A \(param) added to \(super.method1(param))"
}
}
...
// ---------- ClassB.swift ----------
public class B:A
{
override public var method1:(Int) -> String { return doMethod1 }
}
extension B
{
private func doMethod1(param:Int) -> String
{
return "B \(param) added to \(super.method1(param))"
}
}
Each class's extension are able to use the same method names for the implementation because they are private and not visible to each other (as long as they are in separate files).
As you can see inheritance (using the variable name) works properly using super.variablename
BaseClass().method1(123) --> "BaseClass 123"
A().method1(123) --> "A 123 added to BaseClass 123"
B().method1(123) --> "B 123 added to A 123 added to BaseClass 123"
(B() as A).method1(123) --> "B 123 added to A 123 added to BaseClass 123"
(B() as BaseClass).method1(123) --> "B 123 added to A 123 added to BaseClass 123"
This answer it not aimed at the OP, other than the fact that I felt inspired to respond by his statement, "I tend to only put the necessities (stored properties, initializers) into my class definitions and move everything else into their own extension ...". I'm primarily a C# programmer, and in C# one can use partial classes for this purpose. For example, Visual Studio places the UI-related stuff in a separate source file using a partial class, and leaves your main source file uncluttered so you don't have that distraction.
If you search for "swift partial class" you'll find various links where Swift adherents say that Swift doesn't need partial classes because you can use extensions. Interestingly, if you type "swift extension" into the Google search field, its first search suggestion is "swift extension override", and at the moment this Stack Overflow question is the first hit. I take that to mean that problems with (lack of) override capabilities are the most searched-for topic related to Swift extensions, and highlights the fact that Swift extensions can't possibly replace partial classes, at least if you use derived classes in your programming.
Anyway, to cut a long-winded introduction short, I ran into this problem in a situation where I wanted to move some boilerplate / baggage methods out of the main source files for Swift classes that my C#-to-Swift program was generating. After running into the problem of no override allowed for these methods after moving them to extensions, I ended up implementing the following simple-minded workaround. The main Swift source files still contain some tiny stub methods that call the real methods in the extension files, and these extension methods are given unique names to avoid the override problem.
public protocol PCopierSerializable {
static func getFieldTable(mCopier : MCopier) -> FieldTable
static func createObject(initTable : [Int : Any?]) -> Any
func doSerialization(mCopier : MCopier)
}
.
public class SimpleClass : PCopierSerializable {
public var aMember : Int32
public init(
aMember : Int32
) {
self.aMember = aMember
}
public class func getFieldTable(mCopier : MCopier) -> FieldTable {
return getFieldTable_SimpleClass(mCopier: mCopier)
}
public class func createObject(initTable : [Int : Any?]) -> Any {
return createObject_SimpleClass(initTable: initTable)
}
public func doSerialization(mCopier : MCopier) {
doSerialization_SimpleClass(mCopier: mCopier)
}
}
.
extension SimpleClass {
class func getFieldTable_SimpleClass(mCopier : MCopier) -> FieldTable {
var fieldTable : FieldTable = [ : ]
fieldTable[376442881] = { () in try mCopier.getInt32A() } // aMember
return fieldTable
}
class func createObject_SimpleClass(initTable : [Int : Any?]) -> Any {
return SimpleClass(
aMember: initTable[376442881] as! Int32
)
}
func doSerialization_SimpleClass(mCopier : MCopier) {
mCopier.writeBinaryObjectHeader(367620, 1)
mCopier.serializeProperty(376442881, .eInt32, { () in mCopier.putInt32(aMember) } )
}
}
.
public class DerivedClass : SimpleClass {
public var aNewMember : Int32
public init(
aNewMember : Int32,
aMember : Int32
) {
self.aNewMember = aNewMember
super.init(
aMember: aMember
)
}
public class override func getFieldTable(mCopier : MCopier) -> FieldTable {
return getFieldTable_DerivedClass(mCopier: mCopier)
}
public class override func createObject(initTable : [Int : Any?]) -> Any {
return createObject_DerivedClass(initTable: initTable)
}
public override func doSerialization(mCopier : MCopier) {
doSerialization_DerivedClass(mCopier: mCopier)
}
}
.
extension DerivedClass {
class func getFieldTable_DerivedClass(mCopier : MCopier) -> FieldTable {
var fieldTable : FieldTable = [ : ]
fieldTable[376443905] = { () in try mCopier.getInt32A() } // aNewMember
fieldTable[376442881] = { () in try mCopier.getInt32A() } // aMember
return fieldTable
}
class func createObject_DerivedClass(initTable : [Int : Any?]) -> Any {
return DerivedClass(
aNewMember: initTable[376443905] as! Int32,
aMember: initTable[376442881] as! Int32
)
}
func doSerialization_DerivedClass(mCopier : MCopier) {
mCopier.writeBinaryObjectHeader(367621, 2)
mCopier.serializeProperty(376443905, .eInt32, { () in mCopier.putInt32(aNewMember) } )
mCopier.serializeProperty(376442881, .eInt32, { () in mCopier.putInt32(aMember) } )
}
}
Like I said in my introduction, this doesn't really answer the OP's question, but I'm hoping this simple-minded workaround might be helpful to others who wish to move methods from the main source files to extension files and run into the no-override problem.
Use POP (Protocol-Oriented Programming) to override functions in extensions.
protocol AProtocol {
func aFunction()
}
extension AProtocol {
func aFunction() {
print("empty")
}
}
class AClass: AProtocol {
}
extension AClass {
func aFunction() {
print("not empty")
}
}
let cls = AClass()
cls.aFunction()
Just wanted to add that for Objective-C classes, two separate categories can end up overwriting the same method, and it this case... well... unexpected things can happen.
The Objective-C runtime doesn't make any guarantees about which extension will be used, as described by Apple here:
If the name of a method declared in a category is the same as a method in the original class, or a method in another category on the same class (or even a superclass), the behavior is undefined as to which method implementation is used at runtime. This is less likely to be an issue if you’re using categories with your own classes, but can cause problems when using categories to add methods to standard Cocoa or Cocoa Touch classes.
It's a good thing Swift prohibits this for pure Swift classes, since this kind of overly-dynamic behaviour is a potential source of hard to detect and investigate bugs.