1

是否可以在 Objective C 的 init 方法中返回不同类的实例?我有一个名为:MyCustomClass 的类。我还有另外两个不同的类,称为Class 1and Class2。我要实现的是:当我调用[[MyCustomClass alloc] initWithSomeParameters创建实例Class1Class2取决于某些条件时。

MyCustomClass.m

#import "MyCustomClass.h"
#import "Class1.h"
#import "Class2.h"

-(id) initWithSomeParameters: (id) params{
  id myClass;
  if (someCondition){
    myClass = [[Class1 alloc] initWithSomeParameters:(id) params];
    [myClass setSomething:something];
  }else{
    myClass = [[Class2 alloc] initWithSomeParameters:(id) params];
    [myClass setSomething:something];
  }
  return myClass;
}

...后来我打电话给

id myCustomClass = [[MyCustomClass alloc] initWithSomeParameters:(id) params];

这是一个错误的方法吗?如果是这样,什么是正确的?

4

4 回答 4

3

其他几个人都提到了这一点,但调用的结果[[MyClass alloc] init]必须始终是nil或一种 MyClass。它不必特别是 ; 的实例MyClass。它的后代之一是可能的,如NSArrayor NSString。在代码中,此要求如下所示:

MyClass *a = [[MyClass alloc] init];
NSAssert((a==nil) || [a isKindOfClass:[MyClass class]], @"This must always hold true.");

我从未尝试过实现这一点,但它可能看起来像这样:

- (id)initAsSubclass:(NSString *)sublcassName
{
    Class c = NSClassFromString(subclassName);
    self = [[c alloc] init];
    if (self) {
        // Do Custom Init Here
    }
    return self;
}

关键是:

  • 不要执行[super init]
  • 用 . 创建一个全新的对象+alloc
  • 将新创建的对象分配给self.
  • 如果不使用 ARC,[self autorelease]请在替换值之前执行 ,。(如果当前正在执行代码的对象被释放,可能会导致问题。-autorelease将推迟到本节完成。)
于 2013-11-01T14:41:24.197 回答
1

您应该制作某种控制器来初始化正确的类。您也可以使用类方法实现相同的目的。

并且在体裁上,这个给定的实现很糟糕,因为你分配了一次内存[MyCustomClass alloc],然后-(id)initWithSomeParameters:(id)params你又在分配内存。因此,即使是不同的地址也会被重新发送,这不违反苹果的指导方针,一些苹果类也有这样的行为,但他们这样做是因为优化。但这里是错误的。

于 2013-11-01T14:02:48.637 回答
1

这不是一个好方法。最好使用一些辅助类或我们的工厂模式并为方法提供参数。然后根据参数创建一个类对象并返回。

在不同类的 init 方法中创建不同类的对象并不是一个好方法。

编辑:如果您想根据 iOS 版本显示 UIView 或 UIAlertView ,请这样做。

@interface AlertHelper : NSObject
+ (id)getAlert;
@end

///
@implementation AlertHelper
+(id)getAlert{
NSString *version = [[UIDevice currentDevice] systemVersion];
int ver = [version intValue];
if (ver < 7){
//For iOS 6
return something;
}
else{
//for ios 7
return something
}
}
@end
于 2013-11-01T13:51:12.793 回答
0

这样做的方法是这样的:

创建基类,如:

#import "Base.h"
#import "Class1.h"
#import "Class2.h"

@implementation Base

+ (id)classWithParams:(id)params
{
     id retVal = nil;    

     if (condition_based_on_params_means_creating_class1)
     {
        retVal = [[Class1 alloc] initWithSomeParameters:params];
     }
     else
     {
         retVal = [[Class2 alloc] initWithSomeParameters:params]
     }

     return retVal;
}

@end 

Class1 继承自 Base:

@interface Class1 : Base
{
}
- (id)initWithSomeParameters:(id)parameters;
@end

Class2 继承自 Base:

@interface Class2 : Base
{
}
- (id)initWithSomeParameters:(id)parameters;
@end

最终你将拥有:

Base* a = [Base classWithParams:yourParams];
于 2013-11-01T14:44:39.303 回答