Свифт - метод класса, который должен быть переопределен подклассом


есть ли стандартный способ сделать "чистую виртуальную функцию" в Swift, т. е. тот, который должны переопределяется каждым подклассом, и что, если это не так, вызывает ошибку времени компиляции?

5 67

5 ответов:

у вас есть два варианта:

1. Используйте протокол

определите суперкласс как протокол вместо класса

Pro: проверка времени компиляции, если каждый "подкласс" (не фактический подкласс) реализует требуемый метод(ы)

Con: на "суперкласс" (протокол) не может реализовать методы или свойства

2. Утверждать в супер версии метод

пример:

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

class Subclass : SuperClass {
    override func someFunc() {
    }
}

Pro: можно реализовать методы и свойства в суперклассе

Con: нет проверки времени компиляции

нет никакой поддержки абстрактных классов / виртуальных функций, но вы, вероятно, можете использовать протокол для большинства случаев:

protocol SomeProtocol {
    func someMethod()
}

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

Если SomeClass не реализует someMethod, вы получите эту ошибку времени компиляции:

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

другой обходной путь, если у вас не слишком много "виртуальных" методов, заключается в том, чтобы подкласс передавал "реализации" в конструктор базового класса как объекты функции:

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)
    }
}

следующее позволяет наследовать от класса, а также иметь проверку времени компиляции протокола:)

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() { ... }

}

будучи новичком в разработке iOS, я не совсем уверен, когда это было реализовано, но один из способов получить лучшее из обоих миров-реализовать расширение для протокола:

protocol ThingsToDo {
    func doThingOne()
}

extension ThingsToDo {
    func doThingTwo() { /* Define code here */}
}

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

расширения, что позволяет вам иметь значение по умолчанию для функции, а функция в обычном протоколе все равно дает ошибку времени компиляции, если не определено