我想根据init的参数初始化一个超类的子类的实例:
[[Vehicle alloc] initWithItinerary: shortWay]; // returns a bicycle
[[Vehicle alloc] initWithItinerary: longWay]; // returns a car
我找不到像这样的代码示例。我想知道这在目标C中是不是惯用的,或者我只是在寻找合适的位置。
答案 0 :(得分:6)
您可以通过自定义init
方法执行此操作,但这有点单调乏味(您必须调用[super init]
,然后调用[self release]
等。 )。在Vehicle
上创建一个类方法并将其用作工厂方法要简单得多。例如:
+ (id) vehicleWithItinerary:(id)someItinerary {
if ([someItinerary isAShortWay]) {
return [[[Bicycle alloc] initWithItinerary:someItinerary] autorelease];
} else if ([someItinerary isAMediumWay]) {
return [[[RocketPack alloc] initWithItinerary:someItinerary] autorelease];
} else if ([someItinerary isALongWay]) {
return [[[Car alloc] initWithItinerary:someItinerary] autorelease];
}
return nil;
}
答案 1 :(得分:1)
请查看[UIButton buttonWithType:]
以获取Apple如何执行此操作的示例。而不是init,它们使用基类的静态方法来分配适当派生类的实例。
您还可以传递Class
个对象。也许行程知道要分配的Class
或类名。你可以这样做:
[[[itinerary classToAllocate] alloc] initWithItinerary:itinerary];
或
[[NSClassFromString( [itinerary classNameToAllocate] ) alloc] initWithItinerary:itinerary];
您可以在init中释放self并创建一个新对象,尽管很少使用它。请注意递归。
-(id) initWithItinerary:(Itinerary *)inItinerary {
[self release]; // super init never called - safe if you wrote super classes
self = [[[inItinerary classToAllocate] alloc] init];
self.itinerary = inItinerary;
return self;
}
答案 2 :(得分:1)
这称为类集群。几个Cocoa类以这种方式工作,包括NSArray和NSString。从NSArray的init
方法返回的对象永远不是接收消息的对象。然而,在Cocoa之外并不常见,只是因为它通常比人们想要打扰更复杂。基本上,您可以确定要在初始化程序中使用的实际类,创建该类的实例,释放自己并返回另一个实例。
答案 3 :(得分:0)
您可能希望在头文件中添加枚举:
typedef enum {Bike, Car, JetPack
} vehicleType
这样,您的initWithItinerary:
方法可以简单地为:
if(VehicleType == Bike)
{
//do bike stuff
}
else if(VehicleType == Car)
{
//do car stuff
}
答案 4 :(得分:0)
为什么不将方法作为“方式”的一部分,为您提供适当类型的车辆。 e.g。
e.g。
// Somwhere before you use them. Car and Bicycle are subclasses of Vehicle
[shortWay setAppropriateVehicleType: [Bicycle class]];
[longWay setAppropriateVehicleType: [Car class]];
// when you need a vehicle
Vehicle* vehicle = [[[shortWay appropriateVehicleType] alloc] init];