Swift - class method which must be overridden by subclass

前端 未结 6 1134
余生分开走
余生分开走 2020-12-02 10:31

Is there a standard way to make a \"pure virtual function\" in Swift, ie. one that must be overridden by every subclass, and which, if it is not, causes a c

相关标签:
6条回答
  • 2020-12-02 10:39

    Being new to iOS development, I'm not entirely sure when this was implemented, but one way to get the best of both worlds is to implement an extension for a protocol:

    protocol ThingsToDo {
        func doThingOne()
    }
    
    extension ThingsToDo {
        func doThingTwo() { /* Define code here */}
    }
    
    class Person: ThingsToDo {
        func doThingOne() {
            // Already defined in extension
            doThingTwo()
            // Rest of code
        }
    }
    

    The extension is what allows you to have the default value for a function while the function in the regular protocol still provides a compile time error if not defined

    0 讨论(0)
  • 2020-12-02 10:42

    You have two options:

    1. Use a Protocol

    Define the superclass as a Protocol instead of a Class

    Pro: Compile time check for if each "subclass" (not an actual subclass) implements the required method(s)

    Con: The "superclass" (protocol) cannot implement methods or properties

    2. Assert in the super version of the method

    Example:

    class SuperClass {
        func someFunc() {
            fatalError("Must Override")
        }
    }
    
    class Subclass : SuperClass {
        override func someFunc() {
        }
    }
    

    Pro: Can implement methods and properties in superclass

    Con: No compile time check

    0 讨论(0)
  • 2020-12-02 10:49

    The following allows to inherit from a class and also to have the protocol's compile time check :)

    protocol ViewControllerProtocol {
        func setupViews()
        func setupConstraints()
    }
    
    typealias ViewController = ViewControllerClass & ViewControllerProtocol
    
    class ViewControllerClass : UIViewController {
    
        override func viewDidLoad() {
            self.setup()
        }
    
        func setup() {
            guard let controller = self as? ViewController else {
                return
            }
    
            controller.setupViews()
            controller.setupConstraints()
        }
    
        //.... and implement methods related to UIViewController at will
    
    }
    
    class SubClass : ViewController {
    
        //-- in case these aren't here... an error will be presented
        func setupViews() { ... }
        func setupConstraints() { ... }
    
    }
    
    0 讨论(0)
  • 2020-12-02 10:49

    Another workaround, if you don't have too many "virtual" methods, is to have the subclass pass the "implementations" into the base class constructor as function objects:

    class MyVirtual {
    
        // 'Implementation' provided by subclass
        let fooImpl: (() -> String)
    
        // Delegates to 'implementation' provided by subclass
        func foo() -> String {
            return fooImpl()
        }
    
        init(fooImpl: (() -> String)) {
            self.fooImpl = fooImpl
        }
    }
    
    class MyImpl: MyVirtual {
    
        // 'Implementation' for super.foo()
        func myFoo() -> String {
            return "I am foo"
        }
    
        init() {
            // pass the 'implementation' to the superclass
            super.init(myFoo)
        }
    }
    
    0 讨论(0)
  • 2020-12-02 10:49

    You can use protocol vs assertion as suggested in answer here by drewag. However, example for the protocol is missing. I am covering here,

    Protocol

    protocol SomeProtocol {
        func someMethod()
    }
    
    class SomeClass: SomeProtocol {
        func someMethod() {}
    }
    

    Now every subclasses are required to implement the protocol which is checked in compile time. If SomeClass doesn't implement someMethod, you'll get this compile time error:

    error: type 'SomeClass' does not conform to protocol 'SomeProtocol'

    Note: this only works for the topmost class that implements the protocol. Any subclasses can blithely ignore the protocol requirements. – as commented by memmons

    Assertion

    class SuperClass {
        func someFunc() {
            fatalError("Must Override")
        }
    }
    
    class Subclass : SuperClass {
        override func someFunc() {
        }
    }
    

    However, assertion will work only in runtime.

    0 讨论(0)
  • 2020-12-02 11:04

    There isn't any support for abstract class/ virtual functions, but you could probably use a protocol for most cases:

    protocol SomeProtocol {
        func someMethod()
    }
    
    class SomeClass: SomeProtocol {
        func someMethod() {}
    }
    

    If SomeClass doesn't implement someMethod, you'll get this compile time error:

    error: type 'SomeClass' does not conform to protocol 'SomeProtocol'
    
    0 讨论(0)
提交回复
热议问题