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

Почему структуры NSRect, NSPoint и т.д., А не классы?

Мне недавно нужно было создать собственный тип, похожий на NSRect, который имеет точку привязки (по существу, NSRect с другим NSPoint в нем).

После some исследования я обнаружил, что на самом деле мне, вероятно, лучше всего сделать это класс ( как в подклассе NSObject), вместо использования struct. Почему тогда Apple делает эти типы структурными, а не классами? Похоже, что у него будет много преимуществ, таких как отсутствие необходимости в их переносе в NSValues, не нужно использовать функции C для взаимодействия с ними и т.д.

Я уверен, что у них будет причина. Это просто немного меньше использования памяти? Это просто исторический? Или я пропустил нечто большее?

4b9b3361

Ответ 1

Каждая парадигма программирования имеет свои плюсы и минусы, а объектно-ориентированное программирование (OOP) не является исключением.

Все основные преимущества от наличия классов (то есть записи в объектно-ориентированном стиле): encapsulation, polymorphism и inheritance.

Если мы объявим такие простые единицы, как Rect или Point a class, мы не будем использовать что-либо из этого списка, но приведем все недостатки, которые имеет ООП, включая неявную изменчивость, более сложное управление памятью, ссылки на указатели, неявные участники, сломанная инкапсуляция (с сеттерами/геттерами) и т.д. И я не перечисляю здесь сотни анти-шаблонов, которые существуют в ООП.

Я сомневаюсь, что выбор структур для Rect и Point в Cocoa был оправдан C наследием, прежде всего потому, что поддерживаемые классы Objective-C с самого начала, а во-вторых, потому что новый Swift язык не имеет этого наследия, но почти все стандартные типы и контейнеры объявляются в его стандартной библиотеке как структуры, а не классы.

В общем случае, если вам не нужна инкапсуляция, полиморфизм и наследование - вам следует рассмотреть возможность объявления вашего нового объекта как структуры и, по возможности, избегать ООП.

Ответ 2

Главной причиной является производительность - все Cocoa критически важные для производительности API (графика, аудио) имеют тенденцию использовать C-структуры и функции для такого рода целей.

Причины этого в том, что C-компилятор может быть намного легче оптимизирован. Функции C можно назвать более дешевыми, чем методы, и они могут быть встроены в компилятор автоматически, полностью устраняя служебные данные вызова функции. Структуры C выделяются в стеке вместо кучи, что означает, что обработка в основном может выполняться в регистрах или кэшах низкого уровня ЦП вместо вызова в основную память, что в сотни раз медленнее.

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

Ответ 3

Также хорошей точкой является скорость работы. Эти точки и прямоугольники в основном используются для визуализации чего-то и, следовательно, требуют более быстрой работы, чем когда-либо. Вместо выделения объекта, который будет вызывать рекурсивный init, проводя много байтов и циклов процессора для скрытой работы, он просто быстрее говорит "здесь у меня есть 16 байтов, что является 2 CGFloats структуры NSPoint". Это также имеет большое значение при делегировании работы на графический процессор, который ничего не знает о ООП и методах ваших объектов, но нужно много рисовать на экране без сбоев.

Ответ 4

Почему тогда Apple делает эти типы structs, а не классы?

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

Ответ 5

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

Ответ 6

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

Ответ 7

Если вы некоторое время играете с Objective-C, тогда вы будете знать, что это слой OOP поверх coreFoundation, который представляет собой все структуры и "непрозрачные типы" (структуры с секретами).

Например, NSDictionary - это просто обертка вокруг CFtype, CFDictionaryRef. Ну, то, о чем вы спрашиваете здесь, размер, точка, прямоугольник, edgeInsets и т.д. - это всего лишь небольшие типы данных, которые были определены, чтобы не оправдывать обновление. Примитивы (int, double, bool и т.д.) Также не получили (общедоступный) класс для бесплатного моста. Они получили кластер NSNumber, и все эти ребята были собраны вместе в обертке NSValue. Вы можете написать конкретный класс, чтобы обернуть конкретный, если вам нужно...

Ответ 8

Потому что они должны быть типами значений. Точка или прямоугольник фактически не являются объектами. Это всего лишь куча данных. Они не ведут себя, они просто хранят данные, которые вы передаете им. Вы можете написать

CGRect frame = ...
UIView *view1 = [[UIView alloc] initWithFrame:frame];

frame.origin = ...
UIView *view2 = [[UIView alloc] initWithFrame:frame];

И он отлично работает. С ссылочными типами, какие классы, вы измените кадр view1 при перемещении кадра в другое происхождение.

[myRect intersectsWithRect: otherRect] определенно было бы хорошо, и на самом деле Свифт позволяет это делать. Такие типы значений, как структуры и перечисления, могут включать методы в Swift, что позволяет

Ответ 9

Вы используете структуры, когда хотите передать вещи по значению и классам, когда хотите передать их по ссылке.