在Objective-C中是否有与C++的动态强制转换相同的东西?

Dou*_*yle 5 objective-c

如果我有两个类,SubClass和SuperClass:

SuperClass *super = new SuperClass();
SubClass *sub = new SubClass();
SubClass *sub_pointer;

// **The nice one-line cast below**
sub_pointer = dynamic_cast<SubClass*> super;
// Prints NO
printf("Is a subclass: %s\n", sub_pointer ? "YES" : "NO");

sub_pointer = dynamic_cast<SubClass*> sub;
// Prints YES
printf("Is a subclass: %s\n", sub_pointer ? "YES" : "NO");
Run Code Online (Sandbox Code Playgroud)

我可以使用isMemberOfClass在objective-C中完成相同的操作,如下所示:

SuperClass *super = [[SuperClass alloc] init];
SubClass *sub = [[SubClass alloc] init];
SubClass *sub_pointer;
id generic_pointer;

// Not as easy:
generic_pointer = super;
if ([generic_pointer isMemberOfClass:[SubClass class]]) {
  sub_pointer = generic_pointer;
} else {
  sub_pointer = nil;
}
// Logs NO
NSLog(@"Is a subclass: %@", sub_pointer ? @"YES" : @"NO");

generic_pointer = sub;
if ([generic_pointer isMemberOfClass:[SubClass class]]) {
  sub_pointer = generic_pointer;
} else {
  sub_pointer = nil;
}
// Logs YES
NSLog(@"Is a subclass: %@", sub_pointer ? @"YES" : @"NO");
Run Code Online (Sandbox Code Playgroud)

有比这更简单的方法吗?

(PS我知道我不必使用额外的id变量,但是我必须强制执行super to SubClass*,这有时会导致无效的引用,我将不得不在之后进行清理.但是,不那么罗嗦,它在下面)

SuperClass *super = [[SuperClass alloc] init];
SubClass *sub = [[SubClass alloc] init];
SubClass *sub_pointer;

// Not as easy:
sub_pointer = (SubClass*) super;
if (![sub_pointer isMemberOfClass:[SubClass class]]) {
  sub_pointer = nil;
}
// Logs NO
NSLog(@"Is a subclass: %@", sub_pointer ? @"YES" : @"NO");

sub_pointer = (SubClass*) sub;
if (![sub_pointer isMemberOfClass:[SubClass class]]) {
  sub_pointer = nil;
}
// Logs YES
NSLog(@"Is a subclass: %@", sub_pointer ? @"YES" : @"NO");
Run Code Online (Sandbox Code Playgroud)

Pey*_*loW 4

您可以在 NSObject 上添加一个类别来添加您想要的功能。

//NSObject+DynamicCast.h
@interface NSObject (DynamicCast)
-(id)objectIfMemberOfClass:(Class)aClass;
@end

//NSObject+DynamicCast.m
@implementation NSObject (DynamicCast)
-(id)objectIfMemberOfClass:(Class)aClass;
{
  return [self isMemberOfClass:aClass] ? self : nil;
}
@end
Run Code Online (Sandbox Code Playgroud)

然后你可以这样做:

SuperClass *super = [[SuperClass alloc] init];
SubClass *sub = [[SubClass alloc] init];
SubClass *sub_pointer;
id generic_pointer;

// **The nice one-line cast below**
sub_pointer = [super objectIfMemberOfClass:[SubClass class]];
// Prints NO
printf("Is a subclass: %s\n", sub_pointer ? "YES" : "NO");

sub_pointer = [sub objectIfMemberOfClass:[SubClass class]];
// Prints YES
printf("Is a subclass: %s\n", sub_pointer ? "YES" : "NO");
Run Code Online (Sandbox Code Playgroud)