Редактировать: До сих пор похоже, что ответ на мой вопрос: «Вы не можете сделать это в Swift». В настоящее время у меня есть решение, в соответствии с которым имена подклассов перечислены в массиве, и я зацикливаюсь и создаю их экземпляры, чтобы запустить процесс, который я описываю ниже. Если это лучшее, что можно сделать, я переключу его на список, чтобы, по крайней мере, он был определен внешне. Другой вариант - сканировать каталог и загружать все найденные файлы, тогда мне просто нужно убедиться, что выходные данные компилятора для определенных классов помещены в этот каталог ...
Я ищу способ сделать то, что я делал в C ++ несколько раз. По сути, я хочу создать серию конкретных классов, которые реализуют определенный протокол, и я хочу, чтобы эти классы автоматически регистрировали себя так, чтобы я мог получить список всех таких классов. Это классический образец прототипа (см. Книгу GoF) с изюминкой.
Вот мой подход в C ++; возможно, вы можете дать мне несколько идей о том, как это сделать в Swift 4? (Этот код сильно упрощен, но он должен демонстрировать технику.)
class Base {
private:
static set<Base*> allClasses;
Base(Base &); // never defined
protected:
Base() {
allClasses.put(this);
}
public:
static set<Base*> getAllClasses();
virtual Base* clone() = 0;
};
Как видите, каждый раз, когда создается экземпляр подкласса, указатель на объект будет добавлен к статическому Base::allClasses
конструктором базового класса.
Это означает, что каждый класс, унаследованный от Base
, может следовать простому шаблону, и он будет зарегистрирован в Base::allClasses
. Мое приложение может затем получить список зарегистрированных объектов и манипулировать ими по мере необходимости (клонировать новые, вызывать методы получения / установки и т. Д.).
class Derived: public Base {
private:
static Derived global; // force default constructor call
Derived() {
// initialize the properties...
}
Derived(Derived &d) {
// whatever is needed for cloning...
}
public:
virtual Derived* clone() {
return new Derived(this);
}
};
Мое основное приложение может получить список объектов и использовать его для создания новых объектов классов, о которых оно ничего не знает. Базовый класс может иметь метод getName()
, который приложение использует для заполнения меню; теперь меню автоматически обновляется при создании новых подклассов без каких-либо изменений кода в другом месте приложения. Это очень мощный шаблон с точки зрения создания расширяемого, слабо связанного кода ...
Я хочу сделать что-то подобное в Swift. Тем не менее, похоже, что Swift похож на Java в том, что он имеет некоторый загрузчик времени выполнения, и подклассы в этой схеме (такие как Derived
) не загружаются, потому что на них никогда не ссылаются. И если они не загружены, то переменная global
никогда не запускает вызов конструктора, и объект не регистрируется в базовом классе. Точки останова в конструкторе подкласса показывают, что он не вызывается.
Есть ли способ сделать выше? Моя цель - иметь возможность добавить новый подкласс и заставить приложение автоматически определить тот факт, что класс существует, и мне не нужно редактировать файл plist или делать что-либо кроме написания кода и сборки приложения.
Спасибо, что прочитали это далеко - я уверен, что это немного сложный вопрос для понимания (в прошлом у меня были трудности с его объяснением!).