148

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
    }
}
kev
  • 7,712
  • 11
  • 30
  • 41
  • This is pretty close to your other [question](http://stackoverflow.com/questions/24110396/abstract-classes-in-swift-language) but the answer here seems a little better. – David Berry Jun 08 '14 at 20:39
  • The questions are similar but the solutions are far different because a abstract class has different use cases than an abstract function. – kev Jun 08 '14 at 20:43
  • Yep, why I didn't vote to close either, but the answers there won't be useful beyond "you can't" Here you got the best available answer :) – David Berry Jun 08 '14 at 20:47

11 Answers11

231

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
     } 
}
squarefrog
  • 4,750
  • 4
  • 35
  • 64
jaumard
  • 8,202
  • 3
  • 40
  • 63
  • 13
    Alternatively you can use `assert(false, "This method must be overriden by the subclass")`. – Erik Jun 08 '14 at 20:20
  • 24
    or `fatalError("This method must be overridden")` – nathan Jun 08 '14 at 20:20
  • 6
    assertions will require a return statement when a method has a return type. I think fatalError() is better for this one reason – André Fratelli Jul 05 '14 at 00:15
  • 1
    Assertions also seem not to be compiled in for release builds. – JeremyP Jul 09 '14 at 11:08
  • Apparently, neither is `fatalError()` – JeremyP Jul 09 '14 at 11:12
  • 1
    @jaumard If you write something like (No concept of abstract in swift) reference link from apple is appreciated. – Jageen Dec 10 '14 at 06:26
  • 9
    Also there is `preconditionFailure("Bla bla bla")` in Swift which will execute in release builds and also eliminates the need of a return statement. EDIT: Just found out that this method basically is equal to `fatalError()` but it's the more proper way (Better documentation, introduced in Swift along with `precondition()`, `assert()` and `assertionFailure()`, read [here](http://blog.krzyzanowskim.com/2015/03/09/swift-asserts-the-missing-manual/)) – Kametrixom May 15 '15 at 19:59
  • 2
    what if the function has a return type? – LoveMeow May 21 '15 at 21:10
  • If the instance of the SubClass is upCasted to BaseClass, it will call the methods of BaseClass. This is not a good way to do implement abstract methods. – Radian Jheng May 11 '17 at 09:28
  • 1
    This main feature of an abstract class is that there is a compile time check to prevent it from getting instantiated, and the same for the derived (abstract) classes which haven't overridden the pure virtual function. While this solution is a nice work around, it transfers this check to runtime. This is nicely explained by Apple here: https://github.com/apple/swift-evolution/blob/master/proposals/0026-abstract-classes-and-methods.md – Christophe Jun 13 '17 at 06:26
  • Also if you want to call an "abstract" method in another method inside your base class you will end up calling your base method even if it is actually overridden. – Enricoza Dec 04 '19 at 09:56
38

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() {
    }
}
Steve Waddicor
  • 2,197
  • 15
  • 20
  • 30
    This doesn't quite work. If BaseClass wants to call those empty functions, then it would also have to implement the protocol, and then implement the functions. Also the subclass still isn't forced to implement the functions at compile time, and you not compelled to implement the protocol either. – bandejapaisa Dec 30 '14 at 17:05
  • Baseclass has nothing to do with the protocol. I said "for other behaviour". The protocol is introduced for MyClass. As to not being forced to implement at compile time, you clearly haven't actually tried it. – Steve Waddicor Dec 30 '14 at 17:24
  • 8
    That's my point.... BaseClass has nothing to do with the protocol, and to act like an abstract class it should have something to do with it. To clarify what I wrote "If BaseClass wants to call those empty functions, then it would also have to implement the protocol which would force you to implement the functions - which then leads to the Subclass not being forced to implement the functions at compile time, because the BaseClass has already done it". – bandejapaisa Dec 30 '14 at 17:35
  • Baseclass has nothing to do with the protocol. Making it so would be changing the code I presented. There is nothing wrong with the code given. – Steve Waddicor Dec 30 '14 at 17:37
  • To be clear, an abstract function has two features: It no functionality, and it must be overridden. In Swift this is provided by a protocols. There is no other way. Certain other languages allow a base thingy to provide both abstract functions and ordinary virtual functions. Baseclass appears in my example to indicate this is possible with swift but requires both a protocol AND a base class to achieve. "It doesn't quite work" is nonsense. It works perfectly. If you want to say that Swift doesn't provide abstract funcs in the same way as some other particular language, well that's different. – Steve Waddicor Dec 30 '14 at 18:08
  • It is an abstract function in the Swift language. Period. It works perfectly. That it isn't the same as some other unnamed language you're used to is irrelevant. – Steve Waddicor Dec 30 '14 at 18:20
  • 4
    That really depends on how you define "abstract". The whole point of an abstract function is that you can put it on a class that can do normal class things. For example, the reason I want this is because I need to define a static member which you can't seem to do with protocols. So it's hard for me to see that this meets the useful point of an abstract function. – Puppy Sep 11 '15 at 11:21
  • 1
    I think you can use a combination of Protocols and the new Protocol Extensions to get a better solution than abstract base classes. – Glenn Howes Oct 12 '15 at 17:35
  • 4
    I think the concern with the upvoted comments above is that this does not conform to the Liskov Substitution principle which states "objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program." It's assumed this is an abstract type. This is particularly important in the case of Factory Method pattern where the base class is responsible for creating and storing properties that originate from the sub class. – David James Nov 19 '15 at 16:27
  • 2
    An abstract base class and a protocol are not the same thing. – Shoerob Jan 13 '17 at 21:20
32

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
jboi
  • 11,324
  • 4
  • 36
  • 43
  • Maybe not perfect, because I have problems hiding the interface of the class from other classes, but this is enough what I needed to implement classic Factory Method in Swift. – Tomasz Nazarenko Nov 20 '17 at 20:27
  • Hmmm. I like the looks of this answer a lot more, but I'm also not sure it's suitable. I.e., I have a ViewController that can be displaying information for a handful of different types of objects, but the purpose of displaying that information is all the same, with all the same methods, but pulling and putting together the information differently based on the object. So, I have a parent delegate class for this VC, and a subclass of that delegate for each type of object. I instantiate a delegate based on the object passed in. In one example, each object has some relevant comments stored. – Jake T. Jan 23 '18 at 16:23
  • So I have a `getComments` method on the parent delegate. There's a handful of comment types, and I want the ones relevant to each object. So, I want the subclasses to not compile when I do `delegate.getComments()` if I don't override that method. The VC just knows it has a `ParentDelegate` object called `delegate`, or `BaseClassX` in your example, but `BaseClassX` does not have the abstracted method. I'd need the VC to specifically know that it is using the `SubclassedDelegate`. – Jake T. Jan 23 '18 at 16:25
  • I hope I understand you right. If not, do you mind to ask a new question where you can add some code? I think you just need to have an if-statement in ‚doSomethingWithAbstractMethod‘ checking, if delegate is set or not. – jboi Jan 24 '18 at 06:51
  • It' worth mentioning that assigning self to the delegate creates a retain cycle. Maybe it's better to declare it as weak (which is commonly a good idea for delegates) – Enricoza Dec 04 '19 at 10:01
29

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.

BobDickinson
  • 2,156
  • 21
  • 18
  • 4
    Great understanding and good depth on the "the base class does not implement the protocol"... which is kind of the point of an abstract class. I'm baffled that this basic OO feature is missing, but then again, I was raised on Java. – Dan Rosenstark Dec 28 '14 at 16:49
  • 2
    Yet the implementation does not allow to seamlessly implement the Template Function method where the template method calls a wide number of abstract methods implemented in the subclasses. In this case you should write them both as normal methods in the super class, as methods in the protocol and again as implementations in the subclass. In practice you have to write three times the same stuff and only rely on the override check to be sure of not making any disastrous misspelling! I really hope now that Swift is open to developers, full-fledged abstract function shall be introduces. – Fabrizio Bartolomucci Dec 04 '15 at 18:22
  • 1
    So much time, and code could be saved by introducing the "protected" keyword. – Shoerob Jan 13 '17 at 21:25
7

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={ ..... }
    }
}
hariseldon78
  • 1,027
  • 14
  • 22
  • What I like about this approach is that I don't have to remember to implement a protocol in the inheriting class. I have a base class for my ViewControllers, and this is how I enforce ViewController specific, optional functionality (e.g. app became active, etc.) that might get invoked by base class functionality. – ProgrammierTier Jul 23 '15 at 12:46
7

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.

Jorge Ortiz
  • 1,556
  • 1
  • 16
  • 19
5

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 {}
Logan
  • 52,262
  • 20
  • 99
  • 128
3

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.

Erik
  • 12,730
  • 5
  • 36
  • 42
2

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.

Marvin Aguero
  • 91
  • 1
  • 5
1

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.

André Fratelli
  • 5,920
  • 7
  • 46
  • 87
1

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"]
        }
    }
}
interrupt
  • 2,030
  • 17
  • 14