Abstract functions in Swift Language

InheritanceAbstract ClassSwift

Inheritance Problem Overview


I'd like to create an abstract function in swift language. Is it possible?

class BaseClass {
    func abstractFunction() {
        // How do I force this function to be overridden?
    }
}

class SubClass : BaseClass {
    override func abstractFunction() {
        // Override
    }
}

Inheritance Solutions


Solution 1 - Inheritance

There no concept of abstract in Swift (like Objective-C) but you can do this :

class BaseClass {
    func abstractFunction() {
        preconditionFailure("This method must be overridden") 
    } 
}

class SubClass : BaseClass {
     override func abstractFunction() {
         // Override
     } 
}

Solution 2 - Inheritance

What you want is not a base class, but a protocol.

protocol MyProtocol {
    func abstractFunction()
}

class MyClass : MyProtocol {
    func abstractFunction() {
    }
}

If you don't supply abstractFunction in your class it's an error.

If you still need the baseclass for other behaviour, you can do this:

class MyClass : BaseClass, MyProtocol {
    func abstractFunction() {
    }
}

Solution 3 - Inheritance

I port a fair amount of code from a platform that supports abstract base classes to Swift and run in to this a lot. If what you truly want is the functionality of an abstract base class, then that means that this class serves both as an implementation of shared based class functionality (otherwise it would just be an interface/protocol) AND it defines methods that must be implemented by derived classes.

To do that in Swift, you will need a protocol and a base class.

protocol Thing
{
    func sharedFunction()
    func abstractFunction()
}

class BaseThing
{
    func sharedFunction()
    {
        println("All classes share this implementation")
    }
}

Note that the base class implements the shared method(s), but does not implement the protocol (since it doesn't implement all of the methods).

Then in the derived class:

class DerivedThing : BaseThing, Thing 
{
    func abstractFunction() 
    {
        println("Derived classes implement this");
    }
}

The derived class inherits sharedFunction from the base class, helping it satisfy that part of the protocol, and the protocol still requires the derived class to implement abstractFunction.

The only real downside to this method is that since the base class does not implement the protocol, if you have a base class method that needs access to a protocol property/method you will have to override that in the derived class, and from there call the base class (via super) passing self so that the base class has an instance of the protocol with which to do its work.

For example, lets say that sharedFunction needed to call abstractFunction. The protocol would stay the same, and the classes would now look like:

class BaseThing
{
    func sharedFunction(thing: Thing)
    {
        println("All classes share this implementation")
        thing.abstractFunction()
    }
}

class DerivedThing : BaseThing, Thing 
{
    func sharedFunction()
    {
        super.sharedFunction(self)
    }

    func abstractFunction() 
    {
        println("Derived classes implement this");
    }
}

Now the sharedFunction from the derived class is satisfying that part of the protocol, but the derived class is still able to share the base class logic in a reasonably straightforward way.

Solution 4 - Inheritance

This one seems to be the "official" way how Apple is handling abstract methods in UIKit. Take a look at UITableViewController and the way it's working with UITableViewDelegate. One of the very first things you do, is to add a line: delegate = self. Well, that's exactly the trick.

1. Put the abstract method in a protocol
protocol AbstractMethodsForClassX {
    func abstractMethod() -> String
}
2. Write your base class
/// It takes an implementation of the protocol as property (same like the delegate in UITableViewController does)
/// And does not implement the protocol as it does not implement the abstract methods. It has the abstract methods available in the `delegate`
class BaseClassX {
    var delegate: AbstractMethodsForClassX!

    func doSomethingWithAbstractMethod() -> String {
        return delegate.abstractMethod() + " - And I believe it"
    }
}
3. Write the Subclass(es).
/// First and only additional thing you have to do, you must set the "delegate" property
class ClassX: BaseClassX, AbstractMethodsForClassX {
    override init() {
        super.init()
        delegate = self
    }

    func abstractMethod() -> String {return "Yes, this works!"}
}
Here is, how to you use all that
let x = ClassX()
x.doSomethingWithAbstractMethod()

Check with Playground to see the output.

Some Remarks

  • First, a lot of answers were given already. I hope somebody finds all the way down to this one.
  • The question actually was, to find a pattern that implements:
    • A class calls a method, that has to be implemented in one of its derived subclasses (overridden)
    • In best case, if the method is not overridden in the subclass, get an error during compile time
  • The thing about abstract methods is, that they're a mixture of an interface definition and part of an actual implementation in the base class. Both at the same time. As swift is very new and very clean defined, it has no such convienience but "unclean" concepts (yet).
  • To me (a poor old Java guy), this problem evolves from time to time. I've read thru all the answers in this post and this time I think I found a pattern, that looks feasable - at least to me.
  • Update: It looks like the UIKit implementers at Apple use the same pattern. UITableViewController implements UITableViewDelegate but still needs to be registers as delegate by explicitely setting the delegate property.
  • This all is tested on Playground of Xcode 7.3.1

Solution 5 - Inheritance

One way of doing this is to use an optional closure defined in the base class, and the children can choose to implement it or not.

class BaseClass {
    var abstractClosure?:(()->())?
    func someFunc()
    {
        if let abstractClosure=abstractClosure
        {
            abstractClosure()
        }
    } 
}

class SubClass : BaseClass {
    init()
    {
        super.init()
        abstractClosure={ ..... }
    }
}

Solution 6 - Inheritance

Well, I know that I am late to the game and that I might be taking advantage of the changes that have happened. Sorry about that.

In any case, I would like to contribute my answer, because I love doing testing and the solutions with fatalError() is, AFAIK, not testable and the ones with exceptions are much harder to test.

I would suggest to use a more swifty approach. Your goal is to define an abstraction that has some common details, but that is not fully defined, i.e. the abstract method(s). Use a protocol that defines all the expected methods in the abstraction, both the ones that are defined, and also the ones that aren't. Then create a protocol extension that implements the methods that are defined in your case. Finally, any derived class must implement the protocol, which means all the methods, but the ones that are part of the protocol extension already have their implementation.

Extending your example with one concrete function:

protocol BaseAbstraction {
    func abstractFunction() {
        // How do I force this function to be overridden?
    }
}

extension BaseAbstraction {
    func definedFunction() {
        print("Hello")
}

class SubClass : BaseAbstraction {
    func abstractFunction() {
        // No need to "Override". Just implement.
    }
}

Notice that by doing this, the compiler is again your friend. If the method is not "overridden", you will get an error at compile time, instead of the ones that you would get with fatalError() or exceptions that would happen at run time.

Solution 7 - Inheritance

I understand what you're doing now, I think you'd be better off using a protocol

protocol BaseProtocol {
    func abstractFunction()
}

Then, you just conform to the protocol:

class SubClass : BaseProtocol {

    func abstractFunction() {
        // Override
        println("Override")
    }
}

If you class is also a subclass, protocols follow the Superclass:

class SubClass: SuperClass, ProtocolOne, ProtocolTwo {}

Solution 8 - Inheritance

Using assert keyword to enforce abstract methods:

class Abstract
{
    func doWork()
    {
        assert(false, "This method must be overriden by the subclass")
    }
}

class Concrete : Abstract
{
    override func doWork()
    {
        println("Did some work!")
    }
}

let abstract = Abstract()
let concrete = Concrete()

abstract.doWork()    // fails
concrete.doWork()    // OK

However, as Steve Waddicor mentioned you probably want a protocol instead.

Solution 9 - Inheritance

I understand the question and was looking for the same solution. Protocols are not the same as Abstract methods.

In a protocol you need to specify that your class conforms to such protocol, an abstract method means that you have to override such method.

In other words, protocols are kind of optionals, you need to specify the base class and the protocol, if you do not specify the protocol, then you do not have to override such methods.

An abstract method means that you want a base class but need to implement your own method or two, which is not the same.

I need the same behaviour, that is why I was looking for a solution. I guess Swift is missing such feature.

Solution 10 - Inheritance

There's another alternative to this issue, although there still is a downside when compared to @jaumard's proposal; it requires a return statement. Although I miss the point of requiring it, because it consists in directly throwing an exception:

class AbstractMethodException : NSException {
    
    init() {
        super.init(
            name: "Called an abstract method",
            reason: "All abstract methods must be overriden by subclasses",
            userInfo: nil
        );
    }
}

And then:

class BaseClass {
    func abstractFunction() {
        AbstractMethodException.raise();
    }
}

Whatever comes after that is unreachable, so I don't see why force the return.

Solution 11 - Inheritance

I don't know is it going to be useful, but I had a similar issue with abstracted method while trying to build SpritKit game. What I wanted is an abstract Animal class that has methods such as move(), run() etc, but sprite names (and other functionality) should be provided by class children. So I ended up doing something like this (tested for Swift 2):

import SpriteKit

// --- Functions that must be implemented by child of Animal
public protocol InheritedAnimal
{
    func walkSpriteNames() -> [String]
    func runSpriteNames() -> [String]
}


// --- Abstract animal
public class Animal: SKNode
{
    private let inheritedAnimal: InheritedAnimal
    
    public init(inheritedAnimal: InheritedAnimal)
    {
        self.inheritedAnimal = inheritedAnimal
        super.init()
    }
    
    public required init?(coder aDecoder: NSCoder)
    {
        fatalError("NSCoding not supported")
    }
    
    public func walk()
    {
        let sprites = inheritedAnimal.walkSpriteNames()
        // create animation with walking sprites...
    }
    
    public func run()
    {
        let sprites = inheritedAnimal.runSpriteNames()
        // create animation with running sprites
    }
}


// --- Sheep
public class SheepAnimal: Animal
{
    public required init?(coder aDecoder: NSCoder)
    {
        fatalError("NSCoding not supported")
    }

    public required init()
    {
        super.init(inheritedAnimal: InheritedAnimalImpl())
    }
    
    private class InheritedAnimalImpl: InheritedAnimal
    {
        init() {}
        
        func walkSpriteNames() -> [String]
        {
            return ["sheep_step_01", "sheep_step_02", "sheep_step_03", "sheep_step_04"]
        }
        
        func runSpriteNames() -> [String]
        {
            return ["sheep_run_01", "sheep_run_02"]
        }
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionkevView Question on Stackoverflow
Solution 1 - InheritancejaumardView Answer on Stackoverflow
Solution 2 - InheritanceSteve WaddicorView Answer on Stackoverflow
Solution 3 - InheritanceBobDickinsonView Answer on Stackoverflow
Solution 4 - InheritancejboiView Answer on Stackoverflow
Solution 5 - Inheritancehariseldon78View Answer on Stackoverflow
Solution 6 - InheritanceJorge OrtizView Answer on Stackoverflow
Solution 7 - InheritanceLoganView Answer on Stackoverflow
Solution 8 - InheritanceErikView Answer on Stackoverflow
Solution 9 - InheritanceMarvin AgueroView Answer on Stackoverflow
Solution 10 - InheritanceAndré FratelliView Answer on Stackoverflow
Solution 11 - InheritanceinterruptView Answer on Stackoverflow