Любой способ вызвать создание списка всех классов в иерархии в Swift 4? - PullRequest
0 голосов
/ 02 июля 2018

Редактировать: До сих пор похоже, что ответ на мой вопрос: «Вы не можете сделать это в 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 или делать что-либо кроме написания кода и сборки приложения.

Спасибо, что прочитали это далеко - я уверен, что это немного сложный вопрос для понимания (в прошлом у меня были трудности с его объяснением!).

Ответы [ 2 ]

0 голосов
/ 27 июля 2018

Та же лодка. Пока что решение, которое я нашел, состоит в том, чтобы перечислять классы вручную, но не как массив строк (который подвержен ошибкам). Массив классов, таких как этот, выполняет работу:

class AClass {
    class var subclasses: [AClass.Type] {
        return [BClass.self, CClass.self, DClass.self]
    }
}

В качестве бонуса этот подход позволяет мне обрабатывать деревья классов, просто переопределяя subclasses в каждом подклассе.

0 голосов
/ 07 июля 2018

Я отвечаю на свой вопрос; может быть, это поможет кому-то еще.

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

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

Теперь я планирую поместить все подклассы, которые необходимо инициализировать таким образом, в определенный каталог в моем комплекте приложений, тогда мой AppDelegate (или аналогичный класс) будет отвечать за вызов метода, который сканирует каталог, используя имена файлов в качестве Имена классов и создание каждого из них, таким образом, составляя список «зарегистрированных» подклассов.

Когда у меня все заработает, я вернусь и опубликую код здесь (или в проекте GitHub и ссылку на него).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...