programing

목표-C에서 클래스에 대한 개인 메서드를 정의하는 가장 좋은 방법

jooyons 2023. 5. 25. 21:57
반응형

목표-C에서 클래스에 대한 개인 메서드를 정의하는 가장 좋은 방법

저는 방금 오브젝티브-C 프로그램을 프로그래밍하기 시작했고, 자바에 배경이 있는 오브젝티브-C 프로그램을 작성하는 사람들이 개인적인 방법을 어떻게 다루는지 궁금합니다.

저는 몇 가지 관례와 습관이 있을 수 있다는 것을 알고 있으며, 이 질문에 대해 목표-C에서 개인적인 방법을 다루는 데 사람들이 사용하는 최고의 기술을 집계하는 것으로 생각합니다.

당신의 접근 방식에 대한 주장을 게시할 때 포함시켜 주세요.왜 맛있습니까?어떤 단점이 있습니까? (당신이 알고 있는) 그리고 당신이 그것들을 어떻게 처리합니까?


제가 지금까지 발견한 것에 대해서요.

범주를 사용할 수 있습니다. [예:MyClass.m 파일에서 MyClass(Private)]를 정의하여 개인 메서드를 그룹화합니다.

이 접근 방식에는 두 가지 문제가 있습니다.

  1. Xcode(및 컴파일러?)는 해당 @ 구현 블록에서 개인 범주의 모든 메서드를 정의하는지 여부를 확인하지 않습니다.
  2. MyClass.m 파일의 시작 부분에 개인 카테고리를 선언하는 @interface를 넣어야 합니다. 그렇지 않으면 Xcode는 "self is not response to message "private Foo"와 같은 메시지로 불평합니다.

첫 번째 문제는 빈 범주[예:My Class()].
두 번째는 저를 많이 괴롭힙니다.파일 끝 근처에서 개인 방법을 구현(정의)하고 싶습니다. 가능한지 모르겠습니다.

다른 사람들이 이미 말했듯이 목표-C에는 개인적인 방법과 같은 것이 없습니다.X Leopard, 2부터는 빈 Objective-C 2.0(Mac OS X Leopard, iPhone OS 2.0)으로 수 .@interface MyClass ()클래스 확장이라고 합니다.클래스 확장의 고유한 점은 메서드 구현이 동일해야 한다는 것입니다.@implementation MyClass을 다음과합니다.그래서 저는 수업을 다음과 같이 구성합니다.

.h 파일에서:

@interface MyClass {
    // My Instance Variables
}

- (void)myPublicMethod;

@end

.m 파일의 경우:

@interface MyClass()

- (void)myPrivateMethod;

@end

@implementation MyClass

- (void)myPublicMethod {
    // Implementation goes here
}

- (void)myPrivateMethod {
    // Implementation goes here
}

@end

이 접근 방식의 가장 큰 장점은 방법 구현을 (때로는 임의적인) 공개/사설 구분이 아닌 기능별로 그룹화할 수 있다는 것입니다.

목표-C에는 실제로 "개인적인 방법"이 없습니다. 런타임이 어떤 구현을 사용할지 알아낼 수 있다면 말입니다.그러나 문서화된 인터페이스의 일부가 아닌 방법이 없다는 것은 아닙니다.그 방법들은 카테고리가 괜찮다고 생각합니다.그것을 넣는 것보다.@interface당신의 포인트 2와 같은 .m 파일의 맨 위에, 저는 그것을 그것의 .h 파일에 넣었습니다.에서 본 Xcode가 인 것 은 뒤에 하여 이름을 입니다. 제가그규따로칙은는가, Xcode현애 +다클카뒤파이지스구와래니생합각르리테름고에고규라을일이칙분하여의만플지는하재자있원본지동리으로적이에서다곳고른로은▁a▁after▁x▁so▁such▁to▁nameand클가그▁(▁iention▁conv▁with▁a,제카▁file가뒤▁and▁follow▁conv@interface GLObject (PrivateMethods)에서 찾을 수 있습니다.GLObject+PrivateMethods.h헤더 파일을 제공하는 이유는 유닛 테스트 클래스에서 가져올 수 있기 때문입니다. :-)

그런데 .m 파일의 끝 근처에 있는 구현/정의 방법에 관한 한, .m 파일의 맨 아래에 있는 범주를 구현하여 범주를 사용하여 이 작업을 수행할 수 있습니다.

@implementation GLObject(PrivateMethods)
- (void)secretFeature;
@end

또는 클래스 확장자("빈 범주"라고 하는 것)를 사용하여 해당 메서드를 마지막으로 정의합니다.Objective-C 메소드는 구현에서 임의의 순서로 정의되고 사용될 수 있으므로 파일 끝에 "개인" 메소드를 배치하는 것을 막을 수 없습니다.

헤더를 .GLObject+Extension.h필요한 경우 "친구" 또는 "보호된" 가시성을 모방하여 이러한 방법을 사용할 수 있습니다.

이 답변이 원래 작성된 이후로, clang 컴파일러는 Objective-C 메서드에 대해 두 번의 패스를 수행하기 시작했습니다.즉, "개인" 메서드를 완전히 선언하는 것을 피할 수 있으며, 호출 사이트 위에 있든 아래에 있든 컴파일러에서 찾을 수 있습니다.

저는 Objective-C 전문가는 아니지만, 개인적으로 수업의 구현에서 방법을 정의할 뿐입니다.물론, 그것은 그것을 호출하는 모든 방법 앞에 (위에) 정의되어야 하지만, 그것은 확실히 가장 적은 양의 작업을 필요로 합니다.

에서 개인 정의@implementation블록은 대부분의 용도에 적합합니다.▁within에서 이것들을 볼 입니다.@implementation확장이라고도 함) 범주에 .클래스 연속(클래스 확장이라고도 함) 또는 명명된 범주에 선언할 필요가 없습니다.

클래스 과 "class " 사이에 @implementation).

static기능은 특히 민감하거나 속도가 중요한 개인 방법에 매우 유용합니다.

접두사 이름 지정 규칙을 사용하면 실수로 개인 메서드를 재정의하지 않도록 할 수 있습니다(클래스 이름을 접두사 안전으로 찾습니다).

명명된 범주(예:@interface MONObject (PrivateStuff)로드 시 이름 충돌 가능성이 있기 때문에 특별히 좋은 방법은 아닙니다.친구 또는 보호된 방법(매우 드물게 좋은 선택임)에만 유용합니다.불완전한 범주 구현에 대한 경고를 받으려면 실제로 구현해야 합니다.

@implementation MONObject (PrivateStuff)
...HERE...
@end

여기 주석이 달린 치트 시트가 있습니다.

모노오브젝트.h

@interface MONObject : NSObject

// public declaration required for clients' visibility/use.
@property (nonatomic, assign, readwrite) bool publicBool;

// public declaration required for clients' visibility/use.
- (void)publicMethod;

@end

MONObject.m

@interface MONObject ()
@property (nonatomic, assign, readwrite) bool privateBool;

// you can use a convention where the class name prefix is reserved
// for private methods this can reduce accidental overriding:
- (void)MONObject_privateMethod;

@end

// The potentially good thing about functions is that they are truly
// inaccessible; They may not be overridden, accidentally used,
// looked up via the objc runtime, and will often be eliminated from
// backtraces. Unlike methods, they can also be inlined. If unused
// (e.g. diagnostic omitted in release) or every use is inlined,
// they may be removed from the binary:
static void PrivateMethod(MONObject * pObject) {
    pObject.privateBool = true;
}

@implementation MONObject
{
    bool anIvar;
}

static void AnotherPrivateMethod(MONObject * pObject) {
    if (0 == pObject) {
        assert(0 && "invalid parameter");
        return;
    }

    // if declared in the @implementation scope, you *could* access the
    // private ivars directly (although you should rarely do this):
    pObject->anIvar = true;
}

- (void)publicMethod
{
    // declared below -- but clang can see its declaration in this
    // translation:
    [self privateMethod];
}

// no declaration required.
- (void)privateMethod
{
}

- (void)MONObject_privateMethod
{
}

@end

명확하지 않은 또 다른 접근 방식: C++ 유형은 매우 빠르고 훨씬 높은 수준의 제어를 제공하는 동시에 내보내고 로드하는 객체 메서드의 수를 최소화할 수 있습니다.

인스턴스에 포인터를 가져오는 정적 함수를 구현 아래 또는 위에 정의할 수 있습니다.인스턴스 변수에 액세스할 수 있습니다.

//.h file
@interface MyClass : Object
{
    int test;
}
- (void) someMethod: anArg;

@end


//.m file    
@implementation MyClass

static void somePrivateMethod (MyClass *myClass, id anArg)
{
    fprintf (stderr, "MyClass (%d) was passed %p", myClass->test, anArg);
}


- (void) someMethod: (id) anArg
{
    somePrivateMethod (self, anArg);
}

@end

블록을 사용할 수 있다고요?

@implementation MyClass

id (^createTheObject)() = ^(){ return [[NSObject alloc] init];};

NSInteger (^addEm)(NSInteger, NSInteger) =
^(NSInteger a, NSInteger b)
{
    return a + b;
};

//public methods, etc.

- (NSObject) thePublicOne
{
    return createTheObject();
}

@end

이것이 오래된 질문이라는 것은 알고 있지만, 바로 이 질문에 대한 답을 찾고 있을 때 처음 발견한 질문 중 하나입니다.다른 곳에서는 이 해결책에 대해 논의한 적이 없으니, 이에 대해 어리석은 점이 있다면 알려주십시오.

목표 C의 모든 개체는 performSelector: 메서드를 유지하는 NSObject 프로토콜을 준수합니다.저는 또한 이전에 공개적인 수준에서 노출될 필요가 없는 "도와주거나 사적인" 방법을 만들 방법을 찾고 있었습니다.오버헤드가 없고 헤더 파일에 정의할 필요가 없는 개인 메서드를 생성하려면 이 메서드를 시도하십시오.

아래 코드와 유사한 서명을 사용하여 메서드를 정의합니다.

-(void)myHelperMethod: (id) sender{
     // code here...
}

방법을 참조해야 할 때는 선택기로 부르기만 하면 됩니다.

[self performSelector:@selector(myHelperMethod:)];

이 코드 행은 사용자가 만든 메서드를 호출하고 헤더 파일에 정의되지 않은 메서드에 대한 성가신 경고를 표시하지 않습니다.

만약 당신이 피하고 싶다면.@interface 은 다른 수 있습니다.MyClassPrivate.h이상적이지는 않지만 구현을 혼란스럽게 하지는 않습니다.

나의 수업.

interface MyClass : NSObject {
 @private
  BOOL publicIvar_;
  BOOL privateIvar_;
}

@property (nonatomic, assign) BOOL publicIvar;
//any other public methods. etc
@end

나의 클래스 프라이빗.h

@interface MyClass ()

@property (nonatomic, assign) BOOL privateIvar;
//any other private methods etc.
@end

나의 수업

#import "MyClass.h"
#import "MyClassPrivate.h"
@implementation MyClass

@synthesize privateIvar = privateIvar_;
@synthesize publicIvar = publicIvar_;

@end

Xcode는 이름에 "_private"가 있는 .h 파일을 지원합니다.MyClass.m과 MyClass.h가 있고 MyClass_private.h가 있다고 가정해 보겠습니다. 이제는 MyClass_private.h도 사용할 수 있습니다. Xcode가 이를 인식하여 Assistant Editor의 "Counterparts" 목록에 포함합니다.

//MyClass.m
#import "MyClass.h"
#import "MyClass_private.h"

2번 문제를 피할 방법이 없습니다.그것이 바로 C 컴파일러(그리고 목표-C 컴파일러)가 작동하는 방식입니다.XCode 편집기를 사용하는 경우, 기능 팝업을 사용하여 다음을 쉽게 탐색할 수 있습니다.@interface그리고.@implementation파일에 있는 블록.

개인 메서드가 없는 경우의 이점이 있습니다.숨기려던 논리를 별도의 클래스로 이동하여 대리자로 사용할 수 있습니다.이 경우 위임 개체를 비공개로 표시할 수 있으며 외부에서 볼 수 없습니다.논리를 별도의 클래스(여러 개)로 이동하면 프로젝트를 더 잘 설계할 수 있습니다.클래스가 단순해지고 메서드가 올바른 이름을 가진 클래스로 그룹화되기 때문입니다.

다른 사람들이 말했듯이, 개인적인 방법을 정의하는 것은@implementation블록은 대부분의 용도에 적합합니다.

코드 구성이라는 주제에 대해 - 나는 그들을 아래에 함께 두는 것을 좋아합니다.pragma mark privateXcodeXcode에서 보다 할 수 .

@implementation MyClass 
// .. public methods

# pragma mark private 
// ...

@end

언급URL : https://stackoverflow.com/questions/172598/best-way-to-define-private-methods-for-a-class-in-objective-c

반응형