Абстрактные методы в Swift?

У меня есть несколько вопросов для разработчиков Swift относительно концепции абстрактных классов.

  • Как вы определяете абстрактный класс в Swift? Есть ли способ предотвратить создание экземпляра класса, предоставляя инициализатор для использования его подклассов?
  • Как вы определяете абстрактные методы при реализации других? При определении абстрактных методов Apple обычно указывает вам на протоколы (интерфейсы). Но они решают первую часть моего вопроса, так как все методы, которые они определяют, являются абстрактными. Что вы делаете, когда хотите, чтобы в вашем классе были как абстрактные, так и не абстрактные методы?
  • Как насчет дженериков? Возможно, вы подумали об использовании протоколов вместе с расширениями (категориями). Но тогда возникает проблема с generics, потому что протоколы не могут иметь общие типы, только типы.

Я сделал домашнее задание, и я знаю, как решить эти проблемы с помощью методов, таких как fatalError() или preconditionFailure() в суперклассе, а затем переопределить их в базовом классе. Но для меня это кажется уродливым объектом.

Причина, по которой я публикую это, - выяснить, существует ли более общее и универсальное решение.

Спасибо заранее, Petr.

Ответ 1

На сегодняшний день (7 апреля 2016 года) предложение о введении абстрактных классов и методов в Swift (SE-0026) отложено.

Джо Грофф опубликовал следующее в объявлении быстрой эволюции от 7 марта 2016 года:

Предложение отложено из Swift 3. Обсуждение сосредоточено вокруг того, соответствуют ли абстрактные классы в направлении Swift как "ориентированный на протокол" язык. Помимо любых религиозных догм Swift намеревается быть прагматичным языком, который позволяет пользователям выполнять работу. Сегодня дело в том, что одной из первичных целевых платформ Swift является тяжелая структура Cocoa наследования, а протоколы Swift 2 не соответствуют абстрактным классам в нескольких отношениях [...].

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

Я рекомендую вам прочитать полный адрес электронной почты, но я думаю, что вывод такой же, как и в вашем вопросе: мы в настоящее время придерживаемся способа Objective-C делать вещи (поднимая исключения).

Ответ 2

В Swift есть абстрактное понятие нет. Но мы можем достичь этого сценария, используя концепцию Inheritance, такую ​​как код ниже:

class ParentVC:UIViewController {

    func loadInformation() {
    }
}

class ChildVC:ParentVC {

    // This is an Abstract Method
    override func loadInformation() { 
    }
}

Ответ 3

  Как вы определяете абстрактные методы при реализации других?

"Быстрый" способ достижения этого - объединение протоколов и расширений, иногда также typealiases. Для данных вы собираетесь определить абстрактные свойства в протоколе, затем переопределить их в конкретном классе, а затем объединить все это, используя оператор typealias и &:

protocol BaseAbstract: class {
    var data: String { get set }
    func abstractMethod()
    func concreteMethod()
}


extension BaseAbstract {
    // Define your concrete methods that use the abstract part of the protocol, e.g.:
    func concreteMethod() {
        if !data.isEmpty {
            abstractMethod()
        }
    }
}


class BaseImpl {
    // This is required since we can't define properties in extensions.
    // Therefore, we define a class with a concrete property and then 
    // unite it with the protocol above in the typealias below.
    var data: String = "Hello, concrete!"
}


typealias Base = BaseAbstract & BaseImpl // et voila, 'Base' is now ready to be subclassed


class Subclass: Base {
    func abstractMethod() { // enforced by the compiler
    }
}

(Если у вас есть дженерики в этом сценарии, это может стать хитрее. В настоящее время пытаюсь это выяснить.)