Вопрос по objective-c, private-members, c# – , он доступен только в пределах этого файла, что означает, что он фактически является закрытым; он не может быть вызван объектом любого другого класса.

3

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

Соглашение, которое я хочу выяснить, заключается в том, как (используя лучшие практики кодирования для кода производственного уровня) использовать частные методы в классе. Исходя из фона в C #, когда я пишу классы, обычно есть блок кода, который повторяется в нескольких открытых методах (таких как проверка ошибок или настройка соединения службы WCF). Я обычно создаю один блок этого кода и помещаю его в закрытый метод для доступа только этих открытых методов. Таким образом, если мне нужно внести изменение, мне нужно сделать это только в одном месте, в отличие от 10 разных мест в классе, но при этом никогда не дать пользователям возможность вызывать этот закрытый метод. Например:

public Class A
{
    public void method1()
    {
        doErrorChecking()
        // Do more stuff
    }
    public void method2()
    {
        doErrorChecking()
        // Do more stuff
    }     
    private doErrorChecking() { //Error Checking Code}
}

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

Ваш Ответ

3   ответа
3

который абсолютно не может быть переопределен подклассом, вы можете просто сделать обычную функцию C вместо метода. Если функция объявлена ​​в рамках класса@implementation блок, он все еще может получить доступ ко всем частным иварам объекта. Вам нужно будет передать указатель наselfтем не менее, поскольку функция не привязана к определенному объекту

Так это будет выглядеть так:

static BOOL isInValidState(MyClass *);

@implementation MyClass

static BOOL isInValidState(MyClass *self) {
    if (self->somePrivateIvar == nil) {
        return NO;
    }

    if ([self->someString isEqualToString:@"pigsAreFlying"]) {
        return NO;
    }

    return YES;
}

- (void)method1 {
    if (isInValidState(self) == NO) {
        return;
    }
    // Do whatever method 1 does
}

- (void)method2 {
    if (isInValidState(self) == NO) {
        return;
    }
    // Do whatever method 2 does
}

@end

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

9

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

@interface MyClass ()
- (void)_privateMethod:(id)arg;
@end

Разница между продолжением класса и нормальной категорией (такой как@interface MyClass (PrivateMethods)) компилятор потребует от вас реализации методов в вашем главном@implementation блок, а не иметь отдельный@implementation MyClass (PrivateMethods) блок. Это возможно желательно при реализации вспомогательных методов, как вы описали.

С точки зрения именования,довольно часто начинать частные имена методов (и, в этом отношении, имена ivar) с_хотя не все - видимо Appleоставляет за собой это, поэтому вы должны выбрать другой префикс. Язык ничего не навязывает.

Извините, я переключил имена классов на вас. я имел в видуClassA везде я сказалMyClass, В основномClassA.h будет содержать@interface ClassA /*public methods declarations*/ @end, а такжеClassA.m будет содержать@interface ClassA () /*private method declarations*/ @end а также@implementation ClassA /*both private & public method implementations*/ @end. jtbandes
+1 Я ценю, что вы учли мой комментарий :) albertamg
Ответили одновременно, но ваш ответ более полный. Согласовано. Matt
Ух ты. Думаю, я читаю слишком много кода Apple :) jtbandes
О методах префикса с подчеркиванием: «Не используйте символ подчеркивания в качестве префикса для ваших личных методов. Apple оставляет за собой это соглашение». albertamg
3

включите что-то вроде этого выше вашего@implementation:

@interface A ()
- (void) doErrorChecking;
@end

Затем используйте метод в коде по мере необходимости. Хотя из-за динамической природы target-c ни один метод не является по-настоящему закрытым, он будет скрывать метод из файла интерфейса, но технически включать его в ваш собственный «частный» интерфейс. В общем, держи.h файл для методов и свойств, которые подходят для публичного использования, в то же время ограничивая методы и свойства частного использования расширением класса в файле реализации.

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