저는 Mac / iPhone 프로그래밍과 Objective-C를 처음 사용합니다. C #과 Java에는 “generics”가 있는데,이 클래스의 멤버는 선언 된 유형 만 가능합니다. 예를 들어 C #에서
Dictionary<int, MyCustomObject>
정수 키와 MyCustomObject 유형의 값만 포함 할 수 있습니다. Objective-C에도 비슷한 메커니즘이 있습니까?
답변
Xcode 7에서 Apple은 Objective-C에 ‘Lightweight Generics’를 도입했습니다. Objective-C에서는 유형이 일치하지 않으면 컴파일러 경고를 생성합니다.
NSArray<NSString*>* arr = @[@"str"];
NSString* string = [arr objectAtIndex:0];
NSNumber* number = [arr objectAtIndex:0]; // Warning: Incompatible pointer types initializing 'NSNumber *' with an expression of type 'NSString *'
그리고 Swift 코드에서 컴파일러 오류가 발생합니다.
var str: String = arr[0]
var num: Int = arr[0] //Error 'String' is not convertible to 'Int'
경량 제네릭은 NSArray, NSDictionary 및 NSSet과 함께 사용하도록 만들어졌지만 자신의 클래스에 추가 할 수도 있습니다.
@interface GenericsTest<__covariant T> : NSObject
-(void)genericMethod:(T)object;
@end
@implementation GenericsTest
-(void)genericMethod:(id)object {}
@end
Objective-C는 컴파일러 경고와 함께 이전처럼 작동합니다.
GenericsTest<NSString*>* test = [GenericsTest new];
[test genericMethod:@"string"];
[test genericMethod:@1]; // Warning: Incompatible pointer types sending 'NSNumber *' to parameter of type 'NSString *'
그러나 Swift는 일반 정보를 완전히 무시합니다. (Swift 3+에서는 더 이상 적용되지 않습니다.)
var test = GenericsTest<String>() //Error: Cannot specialize non-generic type 'GenericsTest'
이러한 Foundation 컬렉션 클래스 외에도 Objective-C 경량 제네릭은 Swift에서 무시됩니다. 경량 제네릭을 사용하는 다른 유형은 마치 매개 변수가없는 것처럼 Swift로 가져옵니다.
답변
이 답변은 구식이지만 역사적 가치가 있습니다. Xcode 7부터 6 월 ’15의 Connor의 답변이 더 정확합니다.
아니요, Objective-C에는 고유 한 사용자 지정 컬렉션 클래스에서 C ++ 템플릿을 사용하지 않는 한 제네릭이 없습니다 (강력하지 않습니다).
Objective-C에는 기능으로 동적 입력이 있습니다. 즉, 모든 객체가 메시지를 수신 할 수 있으므로 런타임에서 객체 유형에 신경 쓰지 않습니다. 내장 컬렉션에 객체를 추가하면 마치 마치 마치 마치 객체처럼 취급됩니다 id
. 그러나 걱정하지 마십시오. 보통과 같은 객체에 메시지를 보내십시오. 컬렉션의 하나 이상의 객체가 보내는 메시지에 응답하지 않는 한 제대로 작동합니다 .
제네릭은 강력한 정적 형식 언어이므로 Java 및 C #과 같은 언어에서 필요합니다. Objective-C의 다이나믹 한 타이핑 기능과는 완전히 다른 볼 게임입니다.
답변
아니요, 그러나 저장하려는 객체 유형으로 주석을 달 수 있음을 분명히하기 위해 요즘 Java 1.4로 무언가를 작성해야 할 때이 작업을 몇 번 수행했습니다. 예 :
NSMutableArray* /*<TypeA>*/ arrayName = ....
또는
NSDictionary* /*<TypeA, TypeB>*/ dictionaryName = ...
답변
Objective-C에는 제네릭이 없습니다.
배열은 정렬 된 객체 모음입니다. Cocoa는 NSArray, NSMutableArray (NSArray의 서브 클래스) 및 NSPointerArray와 같은 여러 배열 클래스를 제공합니다.
답변
Apple은 XCode 7에서 ObjC에 제네릭을 추가했습니다.
@property NSArray<NSDate *>* dates;
- (NSArray<NSDate *> *)datesBeforeDate:(NSDate *)date;
- (void)addDatesParsedFromTimestamps:(NSArray<NSString *> *)timestamps;
답변
이것은 Xcode 7에서 출시되었습니다 (최종!)
Objective C 코드에서는 컴파일 타임 검사일뿐입니다. 컬렉션에 잘못된 유형을 넣거나 유형이 지정된 속성에 할당하는 경우 런타임 오류가 발생하지 않습니다.
알리다:
@interface FooClass <T> : NSObject
@property (nonatomic) T prop;
@end
사용하다:
FooClass<NSString *> *foo = [[FooClass alloc] init];
NSArray<FooClass<NSString *> *> *fooAry = [NSArray array];
그것들에주의하십시오 *
.
답변
일반 NSArray는 서브 클래 싱 NSArray
을 수행하고 제공된 모든 메소드를보다 제한적인 메소드로 재정 의하여 실현할 수 있습니다 . 예를 들어
- (id)objectAtIndex:(NSUInteger)index
에서 재정의해야 할 것입니다
@interface NSStringArray : NSArray
같이
- (NSString *)objectAtIndex:(NSUInteger)index
NSArray가 NSString 만 포함하도록합니다.
작성된 서브 클래스는 드롭 인 대체품으로 사용될 수 있으며 컴파일러 경고, 특성 액세스, 더 나은 코드 작성 및 Xcode의 완성 기능과 같은 많은 유용한 기능을 제공합니다. 이 모든 것이 컴파일 타임 기능이므로 실제 구현을 재정의 할 필요가 없습니다. NSArray의 메소드를 계속 사용할 수 있습니다.
이것을 자동화하고 그것을 두 개의 문장으로 만 요약 할 수 있습니다. 템플릿이 C 전 처리기 매크로로 제공되는 WMGenericCollection을 사용 하여 자동화를 만들었습니다 .
매크로가 포함 된 헤더 파일을 가져온 후에는 인터페이스 용과 구현 용의 두 가지 문을 사용하여 일반 NSArray를 만들 수 있습니다. 저장하려는 데이터 유형과 서브 클래스의 이름 만 제공하면됩니다. WMGenericCollection은 NSArray
, NSDictionary
및에 대한 템플릿 과 NSSet
변경 가능한 해당 템플릿을 제공합니다 .
예 : List<int>
는이라는 사용자 정의 클래스로 실현 될 수 있으며 NumberArray
다음 명령문으로 작성됩니다.
WMGENERICARRAY_INTERFACE(NSNumber *, // type of the value class
// generated class names
NumberArray, MutableNumberArray)
를 만든 후에는 NumberArray
프로젝트의 어느 곳에서나 사용할 수 있습니다. 의 구문은 <int>
없지만 템플릿으로 클래스로 레이블을 지정하기 위해 고유 한 명명 체계를 선택할 수 있습니다.