Is there an equivalent to NS_REQUIRES_SUPER in Swift? [duplicate] - swift

Is there a Swift equivalent to
__attribute((objc_requires_super))
which gives a warning if a method doesn't call it's super method?
Basically, I want to warn (or even better, throw a compiler error) if an overridden method doesn't call its super method.

No, there is no Swift equivalent to __attribute((objc_requires_super)).
The equivalent feature, Swift Attributes, contains no such attribute.
The section of the Swift inheritance documentation where such a feature would be mentioned says only:
When you provide a method, property, or subscript override for a subclass, it is sometimes useful to use the existing superclass implementation as part of your override.
Note that you can prevent overriding functions using final, so you could effectively accomplish what you want by providing empty overridable methods that are called by non-overridable methods:
class AbstractStarship {
var tractorBeamOn = false
final func enableTractorBeam() {
tractorBeamOn = true
println("tractor beam successfully enabled")
tractorBeamDidEnable()
}
func tractorBeamDidEnable() {
// Empty default implementation
}
}
class FancyStarship : AbstractStarship {
var enableDiscoBall = false
override func tractorBeamDidEnable() {
super.tractorBeamDidEnable() // this line is irrelevant
enableDiscoBall = true
}
}
Subclasses would then override the overridable methods, and it wouldn't matter whether they called super or not since the superclass's implementation is empty.
As Bryan Chen notes in the comments, this breaks down if the subclass is subclassed.
I make no claims to whether this approach is stylistically good, but it is certainly possible.

Related

What is the more accurate difference between function overriding and function mutating? In swift particularly

Essentially both are used to modify behaviour of a function to our custom needs. But why the necessity arise to have two ways to do the same thing when both are used for same purpose.
I'm assuming, if a function has HEAD which takes parameters and a BODY which has a certain functionality with those parameters
Mutating function is used when we have to modify at the HEAD.
Mutating -> HEAD -> parameters and
Overriding function is used when we have to modify at the BODY
Overriding -> BODY -> functionality
I've searched over the internet..but found no satisfactory explanation anywhere. Please help me understand them better. Please correct me if I'm wrong.
Mutating
Swift structs are immutable objects meaning that you cannot change its properties within its functions. You need to explicitly mention that you agree to make changes to its properties by adding the mutating keyword in the function definition. However this mutating jargon is required only for value types in Swift - structs and enums.
struct MutatingExample {
var number: Int = 0
// Add 'mutating' to resolve the error
func changeNumber(changedNumber: Int) {
self.number = changedNumber // Error: Cannot assign to property: 'self' is immutable
}
}
Here is an useful post that might provide you more insights - What does the Swift 'mutating' keyword mean?
Reference types such as class do just fine and allow you to change the properties within their functions.
Override
Override is a concept used in inheritance. By that we can infer that override is applicable to reference types such as class and value type(struct/enums) are out of question.
As the name implies, we use the keyword to override an existing functionality, typically that of a super class. For example,
class Parent {
func getName() {
print("Parent")
}
}
class Child: Parent {
// Add override to resolve error
func getName() {
print("Child") // Error: Overriding declaration requires an 'override' keyword
}
}
Useful link: https://www.hackingwithswift.com/sixty/8/3/overriding-methods

Self property in parent class not working

I have a parent class with a method signature like this:
class MyParent {
func doStuff(property: Self) {
fatalError("Not Implemented")
}
}
I then inherit form it like so:
final class MyInherited: MyParent {
var arbitraryVal:String = "Hello"
override func doStuff(property: MyInherited) {
self.arbitraryVal = property.arbitraryVal
}
}
However, it says that doStuff doesn't override any method from its superclass. Is there a way to do what I'm trying to do here and have a parent class required a method property be of type Self?
This violates LSP. Anything the superclass can do, the subclass must also be able to do. If MyParent.doStuff can accept a MyParent, then MyInherited.doStuff must also be able to accept a MyParent. Otherwise, if you passed this object to a function that accepted a MyParent, how would it type-check a later call to doStuff?
A subclass can restrict what it returns, but it cannot restrict what it accepts. So it's ok for the output of doStuff to be Self, but it's not possible for the input to be Self. The input has to be at least as permissive as its parent.
I would expect that you're receiving an error in MyParent, not just MyInherited. It should say:
Covariant 'Self' can only appear as the type of a property, subscript or method result; did you mean 'MyParent'?
And this is correct. It's not possible to restrict a parameter to a smaller set of values. This isn't a Swift limitation. This is a limitation of any sound type system that includes inheritance.
You can use a protocol instead of a superclass
protocol MyParent {
var arbitraryVal: String { get set }
func doStuff(property: MyParent)
}

Are you required to call the a super class's implementation from each and every subclass's function

e.g. you have a subclass defined which overrides a function f in its superclass. Inside the override, are you required to call the superclass's f function.
The answer to this question is not really related to Swift but it's related to all OOP languages.
The simple answer is: No, you are not required to call the superclass implementation.
Whether you should call the superclass implementation or not should be stated in the documentation. When you are not sure, you should generally always call the super implementation.
You have to consider the fact that the superclass does something inside the method and if you don't call the superclass implementation, the subclass doesn't have to work properly.
Not calling the superclass implementation means that you want to prevent the superclass implementation from happening and that usually means your whole inheritance model is flawed.
One notable exception is the situation when the superclass provides some default implementation which you want to replace inside your subclass (e.g. UIViewController.loadView). That's not a very common use case though.
There are also other obvious exceptions, for example getters. When you are overriding a getter to return a custom object, there is usually no need to call super. However, again, even getters can technically initialize some structures in the superclass and it might be needed to call super.
The answer is false, you don't need to call the superclass method you are overriding in Swift or in OOP in general. That would be a horrible limitation if you did! There are times when you should in fact not call it and perhaps the most common example is when you create a UIViewController programmatically and have to override loadView() without calling super.loadView().
The default is that you call super, unless you know you're not breaking that function.
I've created a gist. You can copy it to your own playground and play around with it. But the answer is:
I had this exact confusion of yours. You're basically asking what's the difference between extending behavior vs. overriding behavior.
Swift doesn't do a good a job of telling your their difference.
What they both share is that both need to mark the function with override, but sometimes you're doing something in addition to the superclass's implementation (extending), and sometimes you're just completely rewriting it (overriding)
Suppose we have the following class:
class Person {
var age : Int?
func incrementAge() {
guard age != nil else {
age = 1
return
}
age! += 1
}
func eat() {
print("eat popcorn")
}
}
We can just initialize it and do:
var p1 = Person()
p1.incrementAge() // works fine
Now suppose we did this:
class Boy : Person{
override func incrementAge() {
age! += 2
}
}
var b1 = Boy()
b1.incrementAge()
What do you think is going to happen?!
It will crash. Because in the super class, we're doing a nil check for age, but in our subclass we never call super
To make it work we have to call super.
class GoodBoy : Person{
override func incrementAge() {
super.incrementAge()
age! += 2
}
}
var b2 = GoodBoy()
b2.incrementAge() // works fine.
We could get away without calling super directly.
class AlternateGoodBoy : Person{
override func incrementAge() {
guard age != nil else {
age = 1
return
}
age! += 2
}
}
var b3 = AlternateGoodBoy()
b3.incrementAge() // works fine.
^^ The above works, yet the superclass's implementation is not always known to us. A real example is UIKit. We don't know what happens really when viewDidLoad is called. Hence we must call super.viewDidLoad
That being said sometimes we could just not call super and be totally fine because we know what super does or maybe just don't care and want to completely get rid of it. e.g. :
class Girl : Person{
override func eat() {
print("eat hotdog")
}
}
var g1 = Girl()
g1.eat() // doesn't crash, even though you overrode the behavior. It doesn't crash because the call to super ISN'T critical
Yet the most common case is that you call super, but also add something on top of it.
class Dad : Person {
var moneyInBank = 0
override func incrementAge() {
super.incrementAge()
addMoneyToRetirementFunds()
}
func addMoneyToRetirementFunds() {
moneyInBank += 2000
}
}
var d1 = Dad()
d1.incrementAge()
print(d1.moneyInBank) // 2000
Pro tip:
Unlike most overrides where you first call super then the rest, for a tearDown function, it’s best to call super.tearDown() at the end of the function. In general, for any 'removal' functions, you'd want to call super at the end. e.g. viewWillDisAppear/viewDidDisappear

Can a Swift class be extended multiple times with the same methods?

I am designing a framework that uses protocols and extensions to allow for third-parties to add support for my framework to their existing classes.
I'd also like to include some built-in extensions for known classes like UIView, but I don't want to prevent users from defining their own additional support for the same classes.
My question is is there any way that I can extend the same class twice, and override the same (protocol) method in that class both times, while still having some way to call the other if the first one fails.
Elaboration: I really have three goals here I want to achieve:
I want to allow users of my framework to provide their own extensions for their own (or any) UIView subclasses.
I also need some way to allow general behavior that can apply to all UIViews as a fallback option (i.e. if the specific class extension can't handle it, fall back on the generic UIView extension).
I'd also like to separate out my own implementation, by providing some built-in generic view handling, but in such a way that it doesn't prevent third parties from also defining their own additional generic handling. (If I can't do this, it's not a big deal, the first two parts are the most important.)
I have part 1 working already. The problem is how to get this fallback behavior implemented. If I do it all with extensions, the subclass will override the superclass's implementation of the protocol method. It could call super.method, but I'd like to avoid putting that responsibility on the subclass (in case the author forgets to call super).
I'd like to do this all from the framework code: first, call the object's protocol method. If it returns false, I'd like to somehow call the generic UIView handler.
Now that I'm typing it all out, I'm wondering if I can just use a different method for the generic fallback and be done with it. I just figured it would be elegant if I could do it all with one method.
No! It can't be extended multiple times.
extension Int {
var add: Int {return self + 100} // Line A
}
extension Int {
var add: Int {return self + 105} //Line B
}
Doing so would create a compile time error ( on Line B) indicating: Invalid redeclaration of 'add'
Swift is a static typing language and helps you find these sorts of errors before runtime
In Objective-C you can write this and still not get an error, however the result would be undefined, because you wouldn't know which method gets loaded first during runtime.
Overriding a single protocol method twice in 2 separate extensions wouldn't work, because the protocol method names would collide. Once compiled, they're all just methods on the same class. With that in mind, perhaps put all the protocol methods in their own extension & call them from within the other ones?
The following could be one general option. Could get messy if you decide to keep adding additional extension functionality.
class baseClass {
//stuff
}
extension baseClass: myProtocol {
override func myProtocolMethod(args) -> returnType {
//Repeat this in a separate extension & your method names collide
var status: Bool
//protocol method code sets status as appropriate...
return status = true ? optOne(status) : optTwo(status)
}
func optOne(status:Bool) -> returnType{
//do the 'true' thing
return returnType
}
func optTwo(status:Bool) -> returnType{
//do the 'false' thing
return returnType
}
}
extension baseClass {
var oneExtension = myProtocolMethod(someArg)
}
extension baseClass {
var twoExtension = myProtocolMethod(someArg)
}
I realize this Question is over a year old and the original poster has probably moved on to other things, but I'd like to share an idea anyways and perhaps get some feedback.
You say that you want a method that can be overwritten multiple times. The short answer, like many in this thread have given is no, but the long answer is yes.
We can solve the issue with a bit of generic magic.
class MyView: UIView {
var customizer: MyProtocol<MyView> = Defaults()
func willCallCustomizer() {
customizer.coolMethod(self)
}
}
// Use this class as if it were a protocol
class MyProtocol<T: UIView>: NSObject {
func coolMethod(_ view: T) {}
}
// Class inherits from the "protocol"
class Defaults: MyProtocol<MyView> {
override func coolMethod(_ view: MyView) {
// Some default behavior
}
}
/// on the clients end...
class CustomerCustomizer: MyProtocol<MyView> {
override func coolMethod(_ view: MyView) {
// customized behavior
}
}
So if the client wants to use their own customizer they can just set it, otherwise it will just use the default one.
myViewInstance.customizer = CustomerCustomizer()
The benefit of this approach is that the client can change the customizer object as many times as they want. Because MyProtocol is generic, it may be used for other UIView's as well; thus fulfilling the role of a protocol.

Why is `required` not a valid keyword on class functions in Swift?

It seems that there are a few situations in which a required keyword on Swift class functions would be extremely beneficial, particularly due to the ability of class functions to return Self.
When returning Self from a class func, there are unfortunately two restrictions that make implementing said function very difficult/inhibitive:
You cannot use Self as a type check inside the function implementation, ie:
class Donut {
class func gimmeOne() -> Self {
// Compiler error, 'Self' is only available in a protocol or as the result of a class method
return Donut() as Self
}
}
You cannot return the actual type of the class itself, ie:
class Donut {
class func gimmeOne() -> Self {
// Compiler error, 'Donut' is not convertible to 'Self'
return Donut()
}
}
The reason for these compiler errors is valid. If you have a GlazedDonut subclass that does not override this class function, it is possible that calling GlazedDonut.gimmeOne() will give you back a Donut, which is not a Self.
It seems this situation could be alleviated by allowing classes to specify these functions with required. This would ensure that any subclasses override the method and encur their own round of type checking, making sure that a GlazedDonut returns itself in all cases, eliminating the possibility for a Donut to come back.
Is there a technical, authoritative reason why this has not been added? I'd like to suggest it as an improvement to the Swift team, but want to ensure there isn't an obvious reason why it has been omitted, or cannot be accomplished.
The idea for this question originates here:
https://stackoverflow.com/a/25924224/88111
required is generally only used on initializers, because initializers are not always inherited in Swift. Therefore, to allow you to call an initializer on a variable class (i.e. a value of metaclass type, say Foo.Type), you need to know that that class Foo, and all possible subclasses, have this initializer.
However, methods (both instance methods and class methods) are always inherited. Therefore, required is not necessary.
By the way, your assertion that "You cannot return the actual type of the class itself" is not true. (In fact, the error "'Self' is only available in a protocol or as the result of a class method" itself says you can return the type of the class itself.) Similar to in Objective-C, you can do:
class Donut {
required init() { }
class func gimmeOne() -> Self {
return self()
}
}
You could use a protocol to make the method 'required'
protocol IDonut{
class func gimmeOne()->Donut;
}
class Donut:IDonut {
class func gimmeOne() -> Donut {
return Donut();
}
}
class GlazedDonut: Donut, IDonut{
override class func gimmeOne()->Donut{
return GlazedDonut();
}
}