Есть ли в Swift стандартный способ сделать "чистую виртуальную функцию", т.е. тот, который должен быть переопределен каждым подклассом, и который, если это не так, вызывает ошибку времени компиляции?
swift
abstract
swift-protocols
JuJoDi
источник
источник
protocol
s (по сравнению сinterface
s в Java). Если вам нужно использовать их как абстрактные методы, посмотрите этот вопрос / ответ: stackoverflow.com/a/39038828/2435872Ответы:
У вас есть два варианта:
1. Используйте протокол
Определите суперкласс как протокол вместо класса
Pro : во время компиляции проверяется, реализует ли каждый "подкласс" (не фактический подкласс) требуемый метод (ы)
Против : "суперкласс" (протокол) не может реализовывать методы или свойства.
2. Утвердить в супер версии метода
Пример:
class SuperClass { func someFunc() { fatalError("Must Override") } } class Subclass : SuperClass { override func someFunc() { } }
Pro : может реализовывать методы и свойства в суперклассе.
Con : нет проверки времени компиляции
источник
fatalError
не обеспечивает проверку во время компиляции, приятно, что компилятор, по крайней мере, достаточно умен, чтобы не требовать от вас предоставления возвращаемого значения для метода при вызове пути выполненияfatalError
.super.someFunc()
из переопределенного метода, вы получаете ошибку, несмотря на то, что вы ее переопределили. Вы знаете, что не должны называть это, но кому-то еще не обязательно это знать, и он просто должен следовать стандартной практике.Следующее позволяет наследовать от класса, а также проверять время компиляции протокола :)
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() { ... } }
источник
Нет никакой поддержки абстрактных классов / виртуальных функций, но вы, вероятно, можете использовать протокол в большинстве случаев:
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) } }
источник
Вы можете использовать протокол против утверждения , как предложено в ответ здесь путем
drewag
. Однако пример протокола отсутствует. Я здесь прикрываюсь,Протокол
protocol SomeProtocol { func someMethod() } class SomeClass: SomeProtocol { func someMethod() {} }
Теперь все подклассы необходимы для реализации протокола, который проверяется во время компиляции. Если SomeClass не реализует someMethod, вы получите эту ошибку времени компиляции:
Примечание: это работает только для самого верхнего класса, реализующего протокол. Любые подклассы могут беспечно игнорировать требования протокола. - так прокомментировал по
memmons
Утверждение
class SuperClass { func someFunc() { fatalError("Must Override") } } class Subclass : SuperClass { override func someFunc() { } }
Однако утверждение будет работать только во время выполнения.
источник
Поскольку я новичок в разработке 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 } }
Расширение - это то, что позволяет вам иметь значение по умолчанию для функции, в то время как функция в обычном протоколе по-прежнему выдает ошибку времени компиляции, если не определена.
источник