2016-12-11 13 views
1

Я понимаю, как структуры и классы (и протоколы) работают на базовом уровне. У меня довольно распространенная ситуация:Подкласс a Struct или аналогичный

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

Я пробовал протоколы и расширения, но тогда, поскольку протокол не был общим, мне не удалось определить (общие) операторы, которые я хотел. Если я использую классы, я не буду копировать их при назначении.

Сегодняшний пример: у меня есть матрица, а SquareMatrix - с помощью определенных квадратных матричных функций. Есть операторы, и матрицы могут быть заполнены любым, что соответствует моему кольцевому протоколу. Я попытался определить почти все функциональные возможности протокола с ассоциированным типом и расширение.

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

Решение благодаря Александру Момльову. Необходимо существенно больше работы, чтобы полностью перевести код в расширение протокола и использовать «Я» для всех соответствующих типов. В расширении компилятор был доволен тем, какими были общие типы.

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

+3

Почтовый код, что вы пробовали и какова фактическая проблема. – shallowThought

ответ

8

Наследование/полиморфизм на основе структуры было бы невозможно по крайней мере по двум причинам (что я могу придумать).

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

    Предположим, что существует структура A и структура B, которая наследуется от A. Всякий раз, когда компилятор видит переменную типа A, он не может быть уверен, что тип выполнения будет действительно A, или если вместо этого использовался B. Если B добавил к новым сохраненным свойствам, которых не было A, тогда размер B будет отличаться (больше), чем A. Компилятор не сможет определить тип среды выполнения и размер этих структур.

  2. Для полиморфизма потребуется таблица функций. Таблица функций будет храниться как статический член типа struct. Но для доступа к этому статическому члену каждому экземпляру структуры понадобится член экземпляра, который кодирует тип экземпляра. Это обычно называют указателем «isa» (как в этом случае - это типA). Это будет 8 байтов служебных (для 64-битных систем) для каждого экземпляра.Учитывая, что Int, Bool, Double и многие другие распространенные типы реализованы как структуры, это было бы недопустимым количеством накладных расходов. Подумайте, Bool - это однобайтовое значение, которое потребует 8 байтов служебных данных. Это 11% эффективности!

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

+0

Спасибо. В этом есть смысл. Я в основном это знал. Мои структуры довольно большие, поэтому накладные расходы не являются проблемой. Теперь я думаю об этом по этому поводу, мне просто придется мириться с классами, потому что мне просто нужен один тип, чтобы иметь больше функциональности, но иногда иногда притворяться, что это более простая версия. Вздох, сегодня для меня нет значений. Я поправлю свой вопрос, чтобы стремиться к «лучшей политике». –

+1

@Richard Birkett Объявить матрицу протокола, добавить поведение по умолчанию в расширение, тогда ваша Struct SquareMatrix может быть матрицей с дополнительным поведением. Типы значений, подтверждающие протокол! – Irfan

+0

Вам не нужно использовать классы, как предлагал @Irfan, просто содержать все функциональные возможности в расширении протокола и соответствовать вашим структурам – Alexander

0

Прежде всего, в быстром протокол может быть общим, если вы будете использовать associatedtype.

С другой стороны, вам нужна семантика значения, поэтому вы можете использовать методологию Copy on Write. Это придаст значение семантике вашим классам (так что они будут такими же безопасными, как и структуры).

Эти два способа могут быть использованы для решения вашей проблемы.