Инициализируйте объект с экземпляром суперкласса - PullRequest
17 голосов
/ 17 мая 2011

Допустим, у нас есть 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? Отказ от ответственности: Ну, я не настолько знаком с концепциями кодирования (или даже вообще не знаком), поэтому, может быть, последнее предложение - чепуха.

Ответы [ 3 ]

2 голосов
/ 18 мая 2011

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

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

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

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

0 голосов
/ 18 мая 2011

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

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

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

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

РЕДАКТИРОВАТЬ: просто как заключительная мысль, так как мы уже говорим об опасных техниках, возможно, вы могли бы создать вспомогательный класс, который будет содержать ивары, которые вы хотите добавить в подкласс. Вот так, теперь яЯ действительно сошел с ума!

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


* Используется для КВО , что интересно.

0 голосов
/ 17 мая 2011

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

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

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

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

UPDATE

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

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

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

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