我怎样才能有一个可以返回任何类型的方法/函数?例如,有时类型需要为float
,有时需要为NSString*
,因此id
无效,因为float
不是id
}。如果它更容易,我不反对在c或c ++函数中这样做。
我需要动态返回类型的原因是因为我使用objc / runtime来获取Ivar。
我希望some_type可以做任何事情:
- (some_type)getIvarWithName:(const char *)name in:(id)obj
{
Ivar ivar(class_getInstanceVariable(object_getClass(obj),name));
return (some_type)ivar;
}
答案 0 :(得分:3)
返回float
包裹的NSNumber
,然后您可以使用id
返回类型。
为了简化它,你甚至可以使用拳击文字,例如:
return @(1.1f);
答案 1 :(得分:1)
首先要考虑的是为什么你需要一个可以返回任何类型的函数。它实际上没有意义,因为您无法将值分配给任何东西,因为您不知道类型。当然,严格处理Obj-C对象时情况不同,因为该语言使用id
关键字的未知对象。未知的物体就像混合Honeycrisp苹果和Macintosh苹果(没有双关语),你想要做的就像混合Honeycrisp苹果和飞机!但是,如果您希望根据参数返回某个类型(例如,为int
参数返回int
,为float
参数返回float
),那么您可以重载功能。否则,只有我知道返回绝对任何东西的方式都是void指针(void *
)。这将指向一大块可以真正成为任何东西的数据。但回到原来的问题。它代表什么,它有多长?祝你好运!
更新:正如其他答案所提到的,您可以将简单数据类型(int
,float
等)包装在NSNumbers或NSValues等对象中,这些对象适合您的情况。但是当扩展到具有复杂类型(如结构)的更一般场景时,这些通常不能包含在内置类中。你需要使用Obj-C创建自己的类。
答案 2 :(得分:0)
Obj-C中没有这种多态性。
如果您事先知道将返回什么,那么您当然可以使用方法。
当您使用NSNumber作为浮点值时,重新启动ID将起作用。
您甚至可以引入一个带有数字或字符串的响应对象,并提供(bool) isNumber
和(bool) isString
方法以供以后处理。
但是你真的要做什么?您在哪种情况下使用它,以及您真正想要实现的目标。对我来说,听起来好像可能有更好的解决方案。
答案 3 :(得分:0)
当然,这是一个奇怪的解决方案,但你有一个奇怪的问题。
您需要启用objective-c ++:将.m文件重命名为.mm 然后你的代码看起来像这样:
void weird_function(int a)
{
switch (a)
{
case 0: throw @"Hello";
default: throw a;
}
}
void some_code(int a)
{
try
{
weird_function(a);
}
catch (int a)
{
NSLog(@"Catch int: %d", a);
}
catch (NSString* str)
{
NSLog(@"Catch string: %@", str);
}
}
你的方法可以实现类似的东西:
union ValueHolder
{
void* voidPtrValue;
int intValue;
float floatValue;
NSString* nssstringValue;
};
- (void)getIvarWithName:(const char *)name in:(id)obj
{
ValueHolder vh;
Ivar ivar = object_getInstanceVariable(obj,name, &vh.voidPtrValue));
if (NULL == ivar)
return;
const char* encoding = ivar_getTypeEncoding(ivar);
if (0 == strcmp(encoding, @encode(int)))
throw vh.intValue;
if (0 == strcmp(encoding, @encode(float)))
throw vh.floatValue;
if (0 == strcmp(encoding, "@\"NSString\""))
throw vh.nsstringValue;
}
答案 4 :(得分:0)
我发现在c ++中使用模板可以使用自定义类型 以下代码最适合我的情况:
template <typename _type>
static inline _type & hookVar(id self, NSString*name)
{
Ivar ivar(class_getInstanceVariable(object_getClass(self),[name UTF8String]));
#if __has_feature(objc_arc)
void *pointer(ivar == NULL ? NULL : reinterpret_cast<char *>((__bridge void *)self) + ivar_getOffset(ivar));
#else
void *pointer(ivar == NULL ? NULL : reinterpret_cast<char *>(self) + ivar_getOffset(ivar));
#endif
return *reinterpret_cast<_type *>(pointer);
}
要调用该函数,我只需使用:
NSWindow *win = hookVar<NSWindow*>(self, @"_window");