ios - objective c 카테고리




카테고리를 통해 Objective c의 메소드 재정의 (2)

Obj-C를 사용하면 카테고리를 사용하여 기존 클래스에 메소드를 추가 할 수 있습니다. 따라서 NSString에 메서드를 추가하면 NSMutableString과 NSString 또는 NSString의 하위 클래스를 상속하는 모든 클래스에서 범주화 된 메서드를 사용할 수 있습니다.

하지만 카테고리를 재정의하는 것을 피해야합니다.

어떤 메소드가 호출 될 지 100 % 확신 할 수 없습니다. 그것은 컴파일러에 의존합니다.

Apple 설명서.

Objective-C 언어는 현재 클래스가 상속하는 메소드 또는 클래스 인터페이스에서 선언 된 메소드를 대체하기 위해 카테고리를 사용할 수 있지만 그렇게하지 않는 것이 좋습니다. 카테고리는 서브 클래스를 대신 할 수 없습니다. 범주를 사용하여 메서드를 재정의하는 몇 가지 중요한 단점이 있습니다. 범주가 상속 된 메서드를 재정의하는 경우 범주의 메서드는 상속 된 구현을 super로 메시지를 통해 호출 할 수 있습니다. 그러나 카테고리가 클래스의 클래스에있는 메소드를 대체하는 경우 원래 구현을 호출 할 방법이 없습니다. 카테고리는 동일한 클래스의 다른 카테고리에서 선언 된 메소드를 안정 적으로 대체 할 수 없습니다. 이 문제는 많은 코코아 클래스가 카테고리를 사용하여 구현되기 때문에 특히 중요합니다. 재정의하려고하는 프레임 워크 정의 메소드 자체가 카테고리에 구현되었을 수 있으므로 어떤 구현이 우선 적용되는지는 정의되지 않습니다. 일부 범주 메서드가있는 경우 모든 프레임 워크에서 동작 변경이 발생할 수 있습니다. 예를 들어, NSObject의 카테고리에서 windowWillClose : delegate 메소드를 오버라이드하면 프로그램의 모든 윈도우 델리게이트가 category 메소드를 사용하여 응답합니다. NSWindow의 모든 인스턴스의 동작이 변경 될 수 있습니다. 프레임 워크 클래스에 추가하는 카테고리로 인해 동작이 신비하게 변경되어 충돌이 발생할 수 있습니다.

다음은 목표 C에서 작동합니다.

// Base Class in ClassA.h and ClassA.m
@interface ClassA : NSObject 
- (NSString *) myMethod;
@end
@implementation ClassA
- (NSString*) myMethod { return @"A"; }
@end

//Category in ClassA+CategoryB.h and ClassA+CategoryB.m
@interface ClassA (CategoryB) 
- (NSString *) myMethod;
@end
@implementation ClassA (CategoryB)
- (NSString*) myMethod { return @"B"; }
@end

문제는 ClassA.h를 가져 와서 메시지를 보내는 경우입니다.

[myClassA myMethod]; //returns B

이게 B 돌려주는 이유는 무엇입니까? ClassA + 카테고리 B를 가져 오지 않습니다.

심지어 futhrer, 내가 다음과 같은 경우 :

// Base Class in ClassA.h and ClassA.m
@interface ClassA : NSObject 
- (NSString *) myMethod;
- (NSString *) mySecondMethod;
@end
@implementation ClassA
- (NSString*) myMethod { return @"A"; }
- (NSString *) mySecondMethod { return [self myMethod]; }
@end

//Category in ClassA+CategoryB.h and ClassA+CategoryB.m
@interface ClassA (CategoryB) 
- (NSString *) myMethod;
@end
@implementation ClassA (CategoryB)
- (NSString*) myMethod { return @"B"; }
@end

mySecondMethod를 호출합니다.

ClassA *a = [[ClassA alloc] init];
NSLog(@"%@",[a myMethod]);

아무도 카테고리 구현의 (가져 오기로 인해) 알지 못하더라도 결과는 여전히 B 가 될 것입니다!

나는 카테고리를 가져오고 있다면 B 를 반환하기 위해서만 제외했다.

그래서 어떤 힌트를 주셔서 감사합니다.


Objective-C 메시징은 동적입니다. 즉, 카테고리를 가져올 지 여부는 중요하지 않습니다. 개체는 메시지를 받고 해당 메서드를 실행합니다.

카테고리가 메소드를 무시하고 있습니다. 즉, 런타임에서 해당 객체에 메시지를 보내면 가져온 객체와 상관없이 항상 오버라이드 된 메소드를 찾을 수 있습니다.

범주를 무시하려면 컴파일하지 말아야하므로 컴파일러 소스에서 범주를 제거 할 수 있습니다.
대안은 서브 클래 싱입니다.

또한 이것을 읽으십시오 :

범주 메서드 이름 충돌 방지

범주에서 선언 된 메서드는 기존 클래스에 추가되므로 메서드 이름에 대해 매우주의해야합니다.

카테고리에서 선언 된 메소드의 이름이 원래 클래스의 메소드 또는 동일한 클래스 (또는 수퍼 클래스)의 다른 카테고리에있는 메소드와 동일한 경우, 메소드 구현에서 사용되는 메소드의 동작은 정의되지 않습니다. 실행 시간. 자신의 클래스에서 카테고리를 사용하는 경우 문제가 될 가능성이 적지 만 카테고리를 사용하여 표준 Cocoa 또는 Cocoa Touch 클래스에 메소드를 추가 할 때 문제가 발생할 수 있습니다.

따라서 명시된 바와 같이 사용자 정의 클래스에서 발생할 가능성이 적으므로 문제가 발생하지 않습니다. 하지만 카테고리를 작성하는 대신 서브 클래 싱을 사용해야합니다 .







category