我想初始化取決於參數初始化一個超類的子類的一個實例:INIT]作爲一個工廠方法
[[Vehicle alloc] initWithItinerary: shortWay]; // returns a bicycle
[[Vehicle alloc] initWithItinerary: longWay]; // returns a car
我無法找到這樣的代碼示例。我想知道在Objective C中這是不是慣用的,或者我只是沒有在正確的地方尋找。
我想初始化取決於參數初始化一個超類的子類的一個實例:INIT]作爲一個工廠方法
[[Vehicle alloc] initWithItinerary: shortWay]; // returns a bicycle
[[Vehicle alloc] initWithItinerary: longWay]; // returns a car
我無法找到這樣的代碼示例。我想知道在Objective C中這是不是慣用的,或者我只是沒有在正確的地方尋找。
查看[UIButton buttonWithType:]
,瞭解Apple如何執行此操作的示例。它們不是使用init,而是使用基類的靜態方法來分配適當的派生類的實例。
您還可以傳遞Class
對象。也許行程知道要分配的Class
或類名。你可以做這樣的事情:
[[[itinerary classToAllocate] alloc] initWithItinerary:itinerary];
或
[[NSClassFromString([itinerary classNameToAllocate]) alloc] initWithItinerary:itinerary];
你被允許釋放自我和創造初始化一個新的對象,雖然這是很少使用。注意遞歸。
-(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;
}
你可以通過自定義的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;
}
您可能要枚舉添加到頭文件:
typedef enum {Bike, Car, JetPack } vehicleType
這樣,你的initWithItinerary:
方法可以簡單地是:
if(VehicleType == Bike)
{
//do bike stuff
}
else if(VehicleType == Car)
{
//do car stuff
}
這是一個頗具創意的方法。 – iter 2010-05-21 04:07:18
這就是所謂的類簇。幾個Cocoa類以這種方式工作,包括NSArray和NSString。從NSArray的init
方法返回的對象永遠不會是收到該消息的同一個對象。然而,可可並不常見,因爲它通常比人們想要的更復雜。基本上,你可以找出你想在初始化器中使用的實際類,創建該類的實例,釋放自己並返回其他實例。
爲什麼不把方法作爲「方式」的一部分,爲您提供適合路線的適當類型的車輛。例如
例如
// 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];
我不知道你是否可以詳細說明你對遞歸的關注。 – iter 2010-05-21 04:08:55
在我的最後一個例子中,基類實現了initWithItinerary。如果派生類也有這樣一個方法,並稱爲超級initWithItinerary它會循環。只要您正在尋找它,就可以輕鬆地進行設計。 – drawnonward 2010-05-21 08:45:21