Can You Override Between Extensions in Swift or Not? (Compiler Seems Confused!)

Can you override between extensions in Swift or not? (Compiler seems confused!)

It seems that overriding methods and properties in an extension works with the
current Swift (Swift 1.1/Xcode 6.1) only for Objective-C compatible
methods and properties.

If a class is derived from NSObject then all its members are automatically available
in Objective-C (if possible, see below). So with

class A : NSObject { }

your example code compiles and works as expected. Your Code Data extension overrides
work because NSManagedObject is a subclass of NSObject.

Alternatively, you can use the @objc attribute for a method or property:

class A { }

class B : A { }

extension A
{
@objc var y : String { get { return "YinA" } }
}

extension B
{
@objc override var y : String { get { return "YinB" } }
}

Methods which are not representable in Objective-C cannot be marked with @objc
and cannot be overridden in a subclass extension. That applies for example to
methods having inout parameters or parameters of an enum type.

Declarations in extensions cannot override yet

The error message is pretty clear (despite the somewhat dubious grammar):

declarations from extensions cannot be overridden yet

You cannot override a function that is declared in an extension (The 'yet' implies that this may be possible in a future version of Swift).

If you want to be able to override extFunction you must declare it in BaseViewController itself, not in an extension.

Declarations from extensions cannot be overridden yet in Swift 4

But in the above scenario, I am not overriding the method isValid() in an extension.

isValid gets declared in an extension.

The error pretty much says that if a function is declared this way, it cannot be overridden.

The statement is valid for both from an extension and in an extension.

Overriding methods in Swift extensions

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" /p>

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. /p>

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.

override does not work inside extension object in swift

The error is quite clear:

You have to move the overriding method from the extension into the class


Or you have to mark the declaration in the base class with @objc and @dynamic

class BaseTableViewCell : UITableViewCell {
@objc class dynamic var identifier : String { return "something" }
}

Can I override a Swift method that has been overridden by an extension?

Extensions can add new functionality to a type, but they cannot
override existing functionality.

Answer is here Swift override function in extension

Swift - How can I override an extension method in a concrete subclass

As others have noted, Swift does not (yet) allow you to override a method declared in a class extension. However, I'm not sure whether you'll ever get the behavior you want even if/when Swift someday allows you to override these methods.

Consider how Swift deals with protocols and protocol extensions. Given a protocol to print some metasyntactic variable names:

protocol Metasyntactic {
func foo() -> String
func bar() -> String
}

An extension to provide default implementations:

extension Metasyntactic {
func foo() -> String {
return "foo"
}

func bar() -> String {
return "bar"
}
}

And a class that conforms to the protocol:

class FooBar : Metasyntactic {
func foo() -> String {
return "FOO"
}

func bar() -> String {
return "BAR"
}
}

Swift will use dynamic dispatch to call the appropriate implementations of foo() and bar() based on each variable's runtime type rather than on the type inferred by the compiler:

let a = FooBar()
a.foo() // Prints "FOO"
a.bar() // Prints "BAR"

let b: Metasyntactic = FooBar()
b.foo() // Prints "FOO"
b.bar() // Prints "BAR"

If, however, we extend the protocol further to add a new method:

extension Metasyntactic {
func baz() -> String {
return "baz"
}
}

And if we override our new method in a class that conforms to the protocol:

class FooBarBaz : Metasyntactic {
func foo() -> String {
return "FOO"
}

func bar() -> String {
return "BAR"
}

func baz() -> String {
return "BAZ"
}
}

Swift will now use static dispatch to call the appropriate implementation of baz() based on the type inferred by the compiler:

let a = FooBarBaz()
a.baz() // Prints "BAZ"

let b: Metasyntactic = FooBarBaz()
b.baz() // Prints "baz"

Alexandros Salazar has a fantastic blog post explaining this behavior in depth, but suffice it to say that Swift only uses dynamic dispatch for methods declared in the original protocol, not for methods declared in protocol extensions. I imagine the same would be true of class extensions, as well.



Related Topics



Leave a reply



Submit