Подтвердить что ты не робот

Инициализировать объект с помощью экземпляра суперкласса

Скажем, a имеет Superclass и экземпляр этого класса superclassObject.
Я создаю производную ClassA.

Как я могу создать (инициализировать) объект classAObject производного класса таким образом, чтобы все унаследованные поля были равны единицам superclassObject?

Конечно, я могу перебирать все поля и вручную копировать значения, такие как classAObject.property = [superclassObject.property copy]. Но проблема с этим подходом заключается в том, что я могу не знать (или иметь доступ) все ivars/свойства суперкласса. Есть ли более простой (и более общий) способ?

Кажется, что я пропустил что-то действительно основное...

Я пытаюсь сделать это, потому что я получил уже инициализированный UIView (с фреймом, цветом фона, маской авторезистки и т.д.), и я хочу заменить его своим пользовательским представлением с теми же параметрами.

Обновление 1

Я нашел этот вопрос, и ответ там говорит, что он

обычно не поддерживается ни на одном языке OO

Однако

В Objective-C в некоторых случаях возможно

Хорошо, если он поддерживает не, что мне делать? Если он поддерживает , как я могу это достичь?

Обновление 2

Кажется, я нашел решение для моего конкретного случая этой общей проблемы, которое я буду тестировать и сообщать об этом завтра.

Однако это привело меня к другой идее: что, если я использую NSCoder для кодирования superclassObject (если он реализует <NSCoding>, конечно), а затем вызывает [[ClassA alloc] initWithCoder:coder] с помощью кодера, который знает данные из закодированного superclassObject? Отказ от ответственности: Ну, я не знаком с концепциями кодирования (или даже совсем не с ними), поэтому последнее предложение может быть абсурдным.

4b9b3361

Ответ 1

Если я правильно понял вопрос, у вас есть установленное представление, которое вы хотите изменить на другой класс. Предположительно по причине изменения его функциональности.

Свойства класса клонирования между классами и экземплярами подкачки - единственный способ сделать такие вещи на таких языках, как Java.

Но... в Objective C мы имеем категории. Если все, что вы пытаетесь сделать, это изменить поведение, то, возможно, решение может заключаться в создании категории для UIView, которая выполняет дополнительные или переопределенные функции, которые вам нужны.

Вторая мысль - посмотреть, почему вы не создаете правильный класс и, следовательно, избегаете всей этой проблемы.

Ответ 2

Это определенно возможно с использованием среды выполнения ObjC, но она будет немного волосатой... Это ссылка на документы Apple: Objective-C Время выполнения и пример его использования: Objective-C Программирование времени выполнения.

Вы будете перебирать все свойства, проверять их атрибуты, чтобы узнать те, которые вы можете установить (т.е. опускать свойства readonly), получить их метод getter на суперклассе, прочитать значение и установить с помощью метода setter в подклассе.

В конкретном случае UIView это может сработать - вы будете настраивать до тех пор, пока он не будет работать. Как правило, это может быть трудно: как насчет иваров, которые не подвергаются воздействию свойств? Вы хотите скопировать их все? Затем вам нужно будет проверить свойства, определенные в классе и во всех протоколах, реализуемых классом. И я не уверен, если не будет необходимости перебирать все суперклассы вашего суперкласса, чтобы получить все определенные свойства и ivars.

Но, все же, это возможно.

UPDATE

Если бы вы скопировали переменные экземпляра, то, вероятно, вы, вероятно, были бы настроены, даже не касаясь свойств - я предполагаю, что все состояние сохраняется в ivars в конце концов. Поэтому в этом случае также не нужно касаться определенных протоколом свойств.

Но другое решение, которое может работать достаточно хорошо, - это просто придерживаться общедоступного интерфейса (ну, собственно, его часть: именно то, что представляется как данные, а не функциональность): чтение данных через свойства суперкласса и установка с использованием свойств производный класс, снова полагая, что классы будут делать правильные вещи с данными. В этом случае свойства протокола одинаково важны, поскольку они также являются частью открытого интерфейса, и их реализация может сохранять состояние в переменных экземпляра.

Опять же, я бы не пробовал этот подход как общее решение для копирования любого класса, а в случае дублирования данных одного определенного класса, который мог бы работать достаточно хорошо, и вы можете легко и тщательно протестировать ваш случай.

Ответ 3

IFF ваш подкласс добавляет к суперклассу только методы, а не какое-либо хранилище (т.е. ivars), тогда вы можете использовать метод получерчной магии *, называемый "isa-swizzling". Роб Напир упоминает об этом, и ссылки на сообщение в блоге, которое объясняет все это.

Каждый экземпляр Objective-C имеет кусок памяти в памяти для своих переменных экземпляра, но реализация методов хранится в другом месте в хранилище для объекта класса. В среде выполнения используется указатель экземпляра isa для доступа к объекту класса.

Таким образом, как показано в связанном сообщении в блоге, можно преобразовать экземпляр одного класса в другой , если они имеют точно такие же поля. Как предупреждает Роб, вы не можете добавить ivars, только измените методы.

Литье (MyDerivedClass *)instanceOfSuperclass влияет только на время компиляции. Все это делает компилятор счастливым, когда он сравнивает типы: он не влияет на поиск методов во время выполнения, поэтому ваш instanceOfSuperclass будет по-прежнему действовать как Superclass.

EDIT: как последняя мысль, так как мы уже говорим об опасных методах, возможно, вы можете создать вспомогательный класс, который будет содержать ивары, которые вы хотите добавить в подкласс. Whew, теперь я действительно сошел с ума!

Я никогда не делал этого сам; Я только сообщаю вам технику, которая может быть вам полезна. Пожалуйста, обратите внимание на все предупреждения, которые вы видите, когда это обсуждается.


* Интересно, что для KVO.