Почему Objective C не поддерживает закрытые методы?

Я видел много стратегий объявления полузакрытых методов в Objective C, но, кажется, нет способа сделать действительно закрытый метод. Я принимаю это. Но, почему это так? Каждое объяснение, которое я имею по существу, говорит, "Вы не можете сделать этого, но здесь являетесь близким приближением".

Существует много ключевых слов, к которым относятся ivars (участники), которые управляют их объемом, например. @private, @public, @protected. Почему это не может быть сделано для методов также? Это кажется на что-то, что время выполнения должно смочь поддерживать. Существует ли базовая философия, которую я пропускаю? Это является преднамеренным?

122
задан null 23 June 2013 в 04:26
поделиться

8 ответов

Ответ ... ну ... просто. Простота и последовательность, на самом деле.

Объектив-C является чисто динамичным в момент рассылки метода. В частности, каждый метод рассылки проходит через то же самое одно и тот же точку разрешения динамического метода, что и каждый другой метод рассылки. Во время выполнения каждый метод реализации имеет то же самое одинаковую экспозицию, и все API, предоставляемые объективным временем выполнения, которые работают с методами и селекторами одинаково одинаково одинаковы.

Как многие ответили (как здесь, так и в других вопросах), поддерживаются частные методы с компиляцией; Если класс не объявляет метод в своем общедоступном интерфейсе, то этот метод может также не существовать, насколько касается вашего кода. Другими словами, вы сможете достичь всех различных комбинаций видимости, желаемой при составлении компиляции, организовав ваш проект соответствующим образом.

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

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

Да, это. Нет никаких оснований, чтобы предположить, что реализатор класса не захочет использовать все объекты объекта C, установленные в реализации, и это означает, что Dynamic Discatch должен произойти. Однако нет особой причины, по которой частные методы не могут быть отправлены специальным вариантом objc_msgsend () , поскольку компилятор знает, что они были частными; I.E. Это может быть достигнуто путем добавления таблицы метода для частного только в классе .

не будет никакого способа для частного метод короткого замыкания этот чек или Пропустите время выполнения?

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

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

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

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

102
ответ дан 24 November 2019 в 01:25
поделиться

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

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

4
ответ дан 24 November 2019 в 01:25
поделиться

Использование:

UPDATE TABLE_A
   SET importantField = (SELECT b.importantfield
                           FROM TABLE_B b
                          WHERE b.matchfield = matchfield
                            AND b.matchfield2 = matchfield2) 

SQL Server не поддерживает псевдонимы таблицы на обновлении таблицы, но вышеупомянутое является коррелированный запрос - эти поля без псевдонима таблицы B Прилагается будет служить значениям из Table_a , потому что у него нет псевдонимов.

Единственный выпуск, кроме то, что есть, если существует несколько B.IMPORTANTFIELD значений для записей с соответствующими записями в Table_a. Используйте:

UPDATE TABLE_A
   SET importantField = (SELECT TOP 1 
                                b.importantfield
                           FROM TABLE_B b
                          WHERE b.matchfield = matchfield
                            AND b.matchfield2 = matchfield2) 

.. Но вы должны использовать порядок , а также вы получите какое-либо случайное значение B.ImportantField .

-121--3866255-

Это проблема с средой выполнения Objective-C. В то время как C / C ++ компилируется в нечитаемый механизм машины, Objective-C все еще поддерживает некоторые читаемые человеком атрибуты, такие как имена методов в качестве строк . Это дает объективную возможность выполнять отражающих функций .

Отредактируйте: Быть отражающим языком без строгих частных методов делает объективную цену более «Pythonic» в том, что вы доверяете другим людям, которые используют ваш код, а не ограничивают, какие методы они могут позвонить. Использование оборотов именования, такие как двойные подчеркивания, предназначены для скрытия вашего кода из повседневного клиентского кодера, но не остановит кодер, нуждающихся в более серьезной работе.

1
ответ дан 24 November 2019 в 01:25
поделиться

Существует два ответа в зависимости от интерпретации вопроса.

Первый - скрывать реализацию метода из интерфейса. Это используется, как правило, с категорией без имени (например, @Interface foo () ). Это позволяет объекту отправлять эти сообщения, но не другие - хотя можно случайно переопределить (или иным образом).

Второй ответ, на предположении, что это о производительности и встроении, стало возможным, но в качестве локальной функции C вместо этого. Если вы хотите «Private Foo ( NSSTRING * ARG )« Метод, вы бы сделали void myclass_foo (myclass * self, nsstring * arg) и вызовите его как функция C, как myclass_foo (self, arg) . Синтаксис отличается, но он действует со зрелыми характеристиками производительности частных методов C ++.

Несмотря на то, что это отвечает на вопрос, я должен указать, что категория без имени - это, безусловно, более распространенная цель - C способ сделать это.

1
ответ дан 24 November 2019 в 01:25
поделиться

Да, это можно сделать без влияния на время выполнения, используя технику, уже используемую компилятором(ами) для работы с C++: name-mangling.

Это не было сделано, так как не было установлено, что это решит некоторые значительные трудности в проблемном пространстве кодирования, которые другие методы (например, префикс или подчеркивание) способны обойти в достаточной степени. ОЖИДАЕТСЯ, что для преодоления укоренившихся привычек нужно больше боли.

Вы можете внести патчи для clang или gcc, которые добавляют частные методы к синтаксису и генерируют искаженные имена, которые он сам распознал во время компиляции (и которые быстро забыл). Тогда другие члены сообщества Objective-C смогут определить, стоит ли это на самом деле или нет. Скорее всего, это будет быстрее, чем пытаться убедить разработчиков.

6
ответ дан 24 November 2019 в 01:25
поделиться

Ответы, приведенные до сих пор, сделайте хорошую работу, отвечая на вопрос с философской перспективы, поэтому я собираюсь позитировать более прагматическую причину: то, что будет получено путем изменения семантики язык? Это достаточно просто для эффективного «скрытия» частных методов. Например, представьте, что у вас есть класс, объявленный в заголовом файле, например:

@interface MyObject : NSObject {}
- (void) doSomething;
@end

Если у вас есть необходимость в «частных» методах, вы также можете поставить это в файл реализации:

@interface MyObject (Private)
- (void) doSomeHelperThing;
@end

@implementation MyObject

- (void) doSomething
{
    // Do some stuff
    [self doSomeHelperThing];
    // Do some other stuff;
}

- (void) doSomeHelperThing
{
    // Do some helper stuff
}

@end

Конечно, это не совсем так же, как C ++ / Java частные методы, но это эффективно достаточно близко, поэтому зачем изменять семантику языка, а также компилятора, время выполнения и т. Д., Чтобы добавить функцию, которая уже эмулирована приемлемый путь? Как отмечалось в других ответах, семантика, проходящая в сообщении - и их зависимость от отражения времени выполнения - создаст обращение с «частными» сообщениями нетривиальными.

13
ответ дан 24 November 2019 в 01:25
поделиться

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

Кроме того, во время выполнения нужно будет проверить, что отправитель частного сообщения имеет тот же класс, что и получатель. Можно было бы также обойти private-методы; если бы класс использовал instanceMethodForSelector:, он мог бы выдать возвращаемое IMP любому другому классу, чтобы они напрямую вызвали private-метод.

Частные методы не могли обойти отправку сообщения. Рассмотрим следующий сценарий:

  1. Класс AllPublic имеет метод public instance method doSomething

  2. Другой класс HasPrivate имеет метод private instance также называемый doSomething

  3. Вы создаете массив, содержащий любое количество экземпляров как AllPublic, так и HasPrivate

  4. Вы имеете следующий цикл:

    for (id anObject в myArray)
     [anObject doSomething];
    

    Если бы вы запустили этот цикл изнутри AllPublic, время выполнения должно было бы остановить отправку doSomething на экземпляры HasPrivate, однако этот цикл был бы полезен, если бы он находился внутри класса HasPrivate.

18
ответ дан 24 November 2019 в 01:25
поделиться

Для обеспечения желаемой безопасности потока необходимо выполнить следующие критерии:

  1. Записи в переменную не зависят от ее текущего значения.
  2. Переменная не участвует в инвариантах с другими переменными.

Поскольку здесь встречаются оба - код - это безопасность потока

-121--3338959-

Это означает, что дайте мне все объекты модели Model , которые имеют 1 , 2 или 3 в качестве своего первичного ключа.

См. Поиск полей - в .

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

{% for object in objects %}
    Some value: {{ object.value }}
{% endfor %}

Я не хочу вас обидеть, но в чем ваша проблема? Все это хорошо описано в документации.

Чтобы узнать, как создать приложение Django, прочитайте учебник или книгу Django .

-121--4648365-

Самым простым решением является объявление некоторых статических функций C в ваших классах Objective-C. Они имеют только область файла в соответствии с правилами C для ключевого слова static и потому могут использоваться только методами в этом классе.

Никакой суеты нет вообще.

7
ответ дан 24 November 2019 в 01:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: