Swift | Вопросы собесов
2.13K subscribers
28 photos
937 links
Download Telegram
Какие есть примитивы в gcd ?
Спросят с вероятностью 18%

Grand Central Dispatch (GCD) предоставляет различные примитивы для управления параллельным выполнением кода в iOS и macOS. Эти примитивы помогают разработчикам эффективно управлять асинхронными задачами, синхронизировать доступ к ресурсам и контролировать поток выполнения программы. Вот основные примитивы, предоставляемые GCD:

1️⃣Dispatch Queues (Очереди)
Это фундаментальный компонент GCD, который управляет выполнением блоков кода (задач). Они бывают двух типов:

Serial Queues (Последовательные очереди): Выполняют задачи одну за другой в порядке их добавления.
Concurrent Queues (Параллельные очереди): Позволяют нескольким задачам выполняться одновременно, но порядок начала и завершения выполнения может отличаться от порядка добавления задач.

2️⃣Dispatch Groups (Группы)
Позволяют объединять несколько задач в одну группу для координированного управления. Вы можете отслеживать, когда все задачи в группе завершены, что особенно полезно при выполнении нескольких асинхронных операций, завершение которых необходимо отслеживать.
let dispatchGroup = DispatchGroup()

dispatchGroup.enter()
DispatchQueue.global().async {
// Задача 1
dispatchGroup.leave()
}

dispatchGroup.enter()
DispatchQueue.global().async {
// Задача 2
dispatchGroup.leave()
}

dispatchGroup.notify(queue: DispatchQueue.main) {
// Вызывается, когда обе задачи завершены
print("Все задачи в группе выполнены.")
}


3️⃣Dispatch Work Items (Элементы работы)
Представляет собой блок кода, который может быть добавлен в очередь для выполнения. Элементы работы можно приостанавливать, возобновлять и отменять, что предоставляет дополнительный контроль над выполнением задач.
var workItem: DispatchWorkItem?

workItem = DispatchWorkItem {
print("Выполнение задачи")
if workItem?.isCancelled ?? false {
return
}
// Продолжение выполнения
}

DispatchQueue.global().async(execute: workItem!)


4️⃣Dispatch Semaphores (Семафоры)
Используются для управления доступом к ограниченному ресурсу. Они позволяют ограничить количество потоков, которые могут одновременно обращаться к этому ресурсу.
let semaphore = DispatchSemaphore(value: 1)

DispatchQueue.global().async {
semaphore.wait() // Ожидание сигнала
// Критическая секция
semaphore.signal() // Отправка сигнала
}


5️⃣Dispatch Sources (Источники событий)
Позволяют вам мониторить различные типы системных событий асинхронно. Это могут быть таймеры, файловые дескрипторы, сигналы и другие источники.

6️⃣Dispatch Barriers (Барьеры)
Используются на параллельных очередях для создания точки синхронизации, в которой очередь приостанавливает выполнение своих параллельных задач до тех пор, пока не выполнится задача с барьером.
let queue = DispatchQueue(label: "com.example.queue", attributes: .

concurrent)
queue.async(flags: .barrier) {
// Задача с барьером
}


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

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
🔥31
Есть ли отличия value тайпа от референса тайпа ?
Спросят с вероятностью 55%

Между типами значений (value types) и ссылочными типами (reference types) существуют существенные отличия, которые влияют на работу с данными.

Основные отличия:

1️⃣Способ хранения:
Value types хранятся в стеке, и их значения копируются при передаче. Это значит, что если вы передадите структуру функции или присвоите её новой переменной, создастся новая копия этого значения.
Reference types хранятся в куче, а переменные хранят ссылки на эти объекты. При передаче переменной класса, вы передаёте ссылку на один и тот же объект, а не его копию.

2️⃣Примеры:
В Swift value types включают структуры (struct), перечисления (enum) и базовые типы данных (Int, String, Array, и т.д.).
Reference types включают классы (class).

3️⃣Идентификация:
Для value types равенство определяется по содержимому объекта. Два объекта считаются равными, если их содержимое идентично.
Для reference types равенство может определяться как равенство по ссылке. Два объекта считаются равными, если они указывают на один и тот же участок памяти.

4️⃣Поведение при передаче данных:
Передача value types ведёт к созданию копии. Изменения одной копии не влияют на другую.
Передача reference types означает передачу ссылки на тот же объект. Изменения в одном месте отразятся на всех ссылках на этот объект.

5️⃣Использование:
Value types обычно используются, когда копирование или независимость данных предпочтительнее. Они обеспечивают более предсказуемое управление памятью, так как Swift автоматически управляет жизненным циклом структур и других типов значений.
Reference types полезны, когда необходимо иметь общее состояние или взаимодействовать с объектами, которые могут изменяться в разных частях программы.

Value types (типы значений) копируются при передаче и обычно используются для базовых типов данных. Они предоставляют простоту и безопасность при работе с данными.
Reference types (ссылочные типы) передаются по ссылке, позволяя разным частям программы взаимодействовать с одним и тем же объектом. Это полезно для работы с комплексными структурами данных и для реализации определённых шаблонов проектирования.

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
4
Какой метод используется для сортировки массива в Swift?
Anonymous Quiz
8%
sortArray()
91%
sorted()
0%
orderArray()
1%
arrange()
Можно сделать так, чтобы отменилась операция во время выполнения в gcd ?
Спросят с вероятностью 18%

В Grand Central Dispatch (GCD) отмена операции не поддерживается напрямую, так как он не предоставляет встроенных механизмов для отмены уже запущенных задач. Однако, вы можете реализовать поддержку отмены операций на уровне вашего приложения, используя кастомные проверки внутри блоков выполнения.

Как реализовать отмену операции

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

1️⃣Определите переменную для отслеживания состояния отмены.
Вы можете использовать переменную типа Bool, которая будет указывать, следует ли продолжать выполнение задачи.

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

3️⃣Изменяйте эту переменную из других частей вашего приложения при необходимости отмены.
Это позволит вам контролировать выполнение задачи из любой части приложения.

Пример:
import Foundation

class TaskHandler {
var isCancelled = false

func performLongRunningTask() {
DispatchQueue.global().async {
for i in 1...10 {
if self.isCancelled {
print("Операция была отменена!")
return
}
sleep(1) // Имитация длительной операции
print("Итерация \(i) завершена")
}
}
}

func cancelTask() {
isCancelled = true
}
}

let taskHandler = TaskHandler()
taskHandler.performLongRunningTask()

// Отменить задачу через 3 секунды
DispatchQueue.global().asyncAfter(deadline: .now() + 3) {
taskHandler.cancelTask()
}


Важные моменты

Проверки отмены должны быть распределены равномерно по всему коду задачи, чтобы обеспечить своевременное реагирование на запросы отмены.
Безопасность доступа к данным: Убедитесь, что доступ к переменной isCancelled потокобезопасен, особенно если вы изменяете её из разных потоков. В приведённом примере, так как доступ к переменной осуществляется только из задач, запущенных на глобальной очереди, проблем с потокобезопасностью не возникает.

Хотя GCD не предоставляет встроенной поддержки отмены задач, вы можете организовать такую поддержку самостоятельно, используя простые проверки состояния в коде своих асинхронных задач.

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Как опциональный тип реализован под капотом ?
Спросят с вероятностью 18%

Опциональный тип (Optional) реализован как перечисление (enum). Это перечисление имеет два случая: .none, который эквивалентен значению nil, и .some(Wrapped), который содержит значение типа Wrapped. Тип Wrapped здесь — это тип данных, который может быть или не быть (то есть может быть опциональным).

Реализация:

Определяет Optional как:
enum Optional<Wrapped> {
case none
case some(Wrapped)
}


Это определение показывает, что Optional является универсальным типом с параметром Wrapped. Он может либо содержать значение (some), либо не содержать его вообще (none).

Примеры:
var optionalInt: Optional<Int> = .some(5)
var nilInt: Optional<Int> = .none

// Swift предоставляет синтаксический сахар для опциональных типов
var optionalIntSugar: Int? = 5
var nilIntSugar: Int? = nil


Работа с ними:

Предоставляет несколько способов для работы с опциональными значениями:

1️⃣Принудительное извлечение (`force unwrapping`):
      let unwrappedInt = optionalIntSugar!

Использование ! для извлечения значения из опционального типа. Это приведет к ошибке времени выполнения, если значение будет nil.

2️⃣Опциональное связывание (`optional binding`):
      if let unwrappedInt = optionalIntSugar {
print("Значение: \(unwrappedInt)")
} else {
print("Нет значения")
}

Это позволяет безопасно извлечь значение, если оно существует.

3️⃣Оператор объединения с nil (`nil coalescing`):
      let number = optionalIntSugar ?? 0

Это позволяет предоставить значение по умолчанию для опционального типа в случае, если он содержит nil.

Особенности:

Каждый опциональный тип на самом деле представляет собой один из двух случаев перечисления Optional.
С точки зрения памяти, опциональный тип потребляет больше ресурсов, чем его неопциональный аналог, потому что он должен хранить дополнительную информацию о том, содержит ли он значение или нет.
Компилятор обрабатывает опциональные типы особым образом, в частности, предоставляя специальный синтаксис (?) и интегрируя проверки на nil в процесс компиляции.

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

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
👍2
Какие типы коллекций существуют ?
Спросят с вероятностью 55%

Существует несколько основных типов коллекций, каждый из которых имеет свои уникальные характеристики и предназначен для решения определённых задач. К основным типам коллекций относятся массивы (Arrays), множества (Sets) и словари (Dictionaries).

1️⃣Массивы (Arrays)

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

Пример:
var someInts = [Int]()
someInts.append(3) // Добавление элемента
someInts = [] // Очистка массива

2️⃣
Множества (Sets)

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

Пример:
var letters = Set<Character>()
letters.insert("a") // Добавление элемента
letters = [] // Очистка множества

3️⃣
Словари (Dictionaries)

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

Пример:
var namesOfIntegers = [Int: String]() // Пустой словарь
namesOfIntegers[16] = "sixteen" // Добавление нового элемента
namesOfIntegers = [:] // Очистка словаря


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

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Какие инициализаторы можно добавить в extension ?
Спросят с вероятностью 18%

С помощью расширений (extensions), вы можете добавлять новые инициализаторы к существующим классам, структурам и перечислениям. Однако существуют определенные ограничения и различия в возможностях добавления инициализаторов в зависимости от типа данных. Рассмотрим более подробно, какие инициализаторы можно добавить через расширения в разных случаях:

1️⃣Структуры (Structs)
Обладают особенностью автоматически создавать "синтезированный" инициализатор, который требует, чтобы все свойства структуры были инициализированы. При добавлении новых инициализаторов через расширения:

Вы можете добавлять дополнительные удобные (convenience) инициализаторы, которые могут облегчить создание экземпляров структуры с предопределенными значениями или упрощенной логикой инициализации.
struct Point {
var x: Double
var y: Double
}

extension Point {
init() {
self.init(x: 0, y: 0)
}
}


2️⃣Классы (Classes)
Добавление инициализаторов к классам через расширения включает в себя более строгие ограничения:

Вспомогательные инициализаторы (Convenience initializers) могут быть добавлены через расширения, но вы не можете добавить назначенные инициализаторы (designated initializers) через расширение.
Вспомогательные инициализаторы должны в конечном итоге вызвать другой существующий инициализатор класса.
class Person {
var name: String
var age: Int

init(name: String, age: Int) {
self.name = name
self.age = age
}
}

extension Person {
convenience init() {
self.init(name: "Unknown", age: 0)
}
}


3️⃣Перечисления (Enums)
Могут получать дополнительные инициализаторы через расширения:

Вы можете добавлять инициализаторы, которые помогут создать экземпляры перечисления на основе различных условий или параметров.
enum TemperatureUnit {
case celsius, fahrenheit, kelvin
}

extension TemperatureUnit {
init?(symbol: Character) {
switch symbol {
case "C":
self = .celsius
case "F":
self = .fahrenheit
case "K":
self = .kelvin
default:
return nil
}
}
}

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

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Какой метод используется для добавления элемента в конец массива в Swift?
Anonymous Quiz
89%
append()
5%
add()
5%
insert()
1%
push()
Что в extension можно добавить, кроме функции ?
Спросят с вероятностью 18%

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

1️⃣Вычисляемые свойства
Расширения могут добавлять новые вычисляемые свойства к типам, но они не могут содержать хранимые свойства или добавлять свойства с наблюдателями за их изменениями.
extension Double {
var km: Double { return self * 1_000.0 }
var m: Double { return self }
var cm: Double { return self / 100.0 }
var mm: Double { return self / 1_000.0 }
}

let oneInch = 25.4.mm
print("One inch is \(oneInch) meters") // Вывод: "One inch is 0.0254 meters"


2️⃣Методы
Расширения могут добавлять новые методы экземпляра и новые методы типа к существующим типам.
extension Int {
func repetitions(task: () -> Void) {
for _ in 0..<self {
task()
}
}
}

3.repetitions {
print("Hello!")
}
// Вывод: "Hello!" будет напечатано три раза


3️⃣Модифицирующие (mutating) методы экземпляра
Позволяет им изменять переменные экземпляра.
extension Int {
mutating func square() {
self = self * self
}
}

var someInt = 3
someInt.square() // someInt теперь равен 9


4️⃣Инициализаторы
Позволяет создавать типы новыми способами.
struct Size {
var width: Double
var height: Double
}

extension Size {
init(squareWithSide side: Double) {
self.width = side
self.height = side
}
}

let squareSize = Size(squareWithSide: 5) // width и height будут равны 5


5️⃣Сабскрипты
Расширения могут добавлять новые сабскрипты к существующим типам.
extension Int {
subscript(digitIndex: Int) -> Int {
var decimalBase = 1
for _ in 0..<digitIndex {
decimalBase *= 10
}
return (self / decimalBase) % 10
}
}

print(746381295[0]) // Выводит 5


6️⃣Вложенные типы
Расширения могут добавлять новые вложенные типы к существующим классам, структурам и перечислениям.
extension Int {
enum Kind {
case negative, zero, positive
}

var kind: Kind {
switch self {
case 0:
return .zero
case let x where x > 0:
return .positive
default:
return .negative
}
}
}


Эти возможности делают расширения чрезвычайно мощным инструментом для модульного дизайна и рефакторинга кода.

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Что такое асинхронная задача ?
Спросят с вероятностью 45%

Асинхронная задача — это операция, которая выполняется параллельно с основным потоком выполнения программы, не блокируя его. Это означает, что программа может продолжать обрабатывать другие задачи, не дожидаясь завершения асинхронной операции. Часто используется для операций, которые могут занимать значительное время, таких как сетевые запросы, чтение или запись файлов, обработка больших объёмов данных и длительные вычислительные операции.

Принцип работы

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

Для работы с асинхронными задачами часто используются замыкания (closures) и различные API, такие как Grand Central Dispatch (GCD) и async/await. Вот пример использования async/await для асинхронной загрузки данных из сети:
func fetchDataAsync() async -> Data? {
let url = URL(string: "https://example.com/data")!
do {
let (data, _) = try await URLSession.shared.data(from: url)
return data
} catch {
print("Ошибка при загрузке данных: \(error)")
return nil
}
}

// Где-то в другом месте вашего кода
Task {
if let data = await fetchDataAsync() {
// Обработка данных
}
}


В этом примере функция fetchDataAsync выполняет асинхронный запрос к серверу и возвращает данные, полученные в ответ. Благодаря использованию async/await, код остаётся читаемым и легко понимаемым, несмотря на асинхронность операции.

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

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
Какое ключевое слово используется для объявления константы в Swift?
Anonymous Quiz
3%
const
95%
let
1%
var
1%
constant
Можно ли совершить реализацию функции в протоколе ?
Спросят с вероятностью 18%

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

Как это работает

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

Пример:
protocol Printable {
func printYourself()
}

extension Printable {
func printYourself() {
print("I am \(self)")
}
}

struct Person: Printable {
var name: String
var age: Int
}

let john = Person(name: "John Doe", age: 30)
john.printYourself() // Вывод: "I am Person(name: "John Doe", age: 30)"


В этом примере, структура Person соответствует протоколу Printable и автоматически получает реализацию метода printYourself через расширение протокола. Метод выводит строковое представление экземпляра.

Преимущества:
1️⃣Код становится более DRY (Don't Repeat Yourself): Расширения протоколов позволяют определить общее поведение в одном месте, а не дублировать код во всех типах, соответствующих протоколу.

2️⃣Повышение гибкости: Можно легко изменять поведение всех типов, соответствующих протоколу, просто изменяя реализацию в расширении протокола.

3️⃣Улучшение тестируемости: Благодаря тому что конкретные реализации сосредоточены в расширениях протоколов, их легче тестировать и поддерживать.

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

Расширения протоколов делают Swift более мощным языком для разработки, обеспечивая гибкость и повторное использование кода.

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
1
Какие отличия MVC от MVP ?
Спросят с вероятностью 18%

MVC (Model-View-Controller) и MVP (Model-View-Presenter) — это два популярных архитектурных паттерна, используемых для создания веб- и настольных приложений. Оба паттерна предназначены для разделения ответственности между компонентами программы, что упрощает управление кодом, его тестирование и поддержку. Вот ключевые отличия между ними:

MVC (Model-View-Controller)

Компоненты:
Model: Содержит бизнес-логику и данные. Оповещает контроллер о изменениях, которые нужно отразить в представлении.
View: Отображает данные (модель) пользователю и отправляет действия пользователя контроллеру.
Controller: Мост между моделью и представлением. Обрабатывает входящие действия и данные от представления, изменяет модель и обновляет представление.

Особенности:
Представление обновляется напрямую моделью, но в более современных интерпретациях (часто веб-фреймворки) контроллер отвечает за обновление представления.
Контроллер связывает модель и представление, обрабатывая логику на основе действий пользователя.

MVP (Model-View-Presenter)

Компоненты:
Model: Также содержит бизнес-логику и данные приложения.
View: Интерфейс, который отображает данные (модель) и делегирует все действия пользователя через интерфейс на Presenter.
Presenter: Получает действия от представления через интерфейс, работает с моделью и обновляет представление. Представление пассивно — оно не содержит никакой логики, кроме логики отображения.

Особенности:
Presenter в MVP не знает о конкретных реализациях представлений. Он работает через абстрактный интерфейс View, что упрощает тестирование.
Представление в MVP полностью пассивно, что значит, что вся логика управления UI переносится в Presenter. Это упрощает модульное тестирование, так как Presenter можно тестировать отдельно от пользовательского интерфейса.

Ключевые отличия:

Связь между компонентами: В MVC контроллер активно связывает модель и представление, в то время как в MVP Presenter обеспечивает двустороннюю связь между моделью и представлением через абстрактный интерфейс.
Роль View: В MVC представление может быть более активным участником (особенно в веб-разработке), принимая решения на основе данных модели. В MVP представление полностью пассивно и все решения по управлению данными и состоянием UI принимаются Presenter'ом.
Тестируемость: MVP часто считается более удобным для модульного тестирования, поскольку Presenter не зависит от конкретных реализаций View и может быть легко протестирован с моками или стабами представления.

Оба паттерна полезны и могут быть использованы в различных сценариях в зависимости от конкретных требований проекта и предпочтений команды.

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
2🔥2
Что такое диспетчеризация ?
Спросят с вероятностью 45%

Диспетчеризация (dispatch) относится к процессу определения того, какой блок кода (или функция) должен быть выполнен в ответ на вызов функции, особенно когда точный метод, который следует вызвать, не может быть определён на момент компиляции. Этот процесс тесно связан с концепцией полиморфизма и механизмами наследования в объектно-ориентированном программировании. Существует несколько ее типов.

Статическая диспетчеризация

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

Динамическая диспетчеризация

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

Множественная диспетчеризация

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

Swift использует как статическую, так и динамическую диспетчеризацию, в зависимости от контекста. Методы структур и перечислений обычно используют статическую диспетчеризацию, что делает их вызов очень быстрым. В то же время, методы классов могут использовать динамическую диспетчеризацию, особенно если они помечены как dynamic или происходят от классов, отмеченных @objc, для совместимости с Objective-C.


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

👉 Можно посмотреть примеры как отвечают люди на этот вопрос, или перейти к списку 823 вопросов на IOS разработчика. Ставь 👍 если нравится контент

🔐 База собесов | 🔐 База тестовых
👍41👾1