实例化子类时,如何在超类中使用 Objective-C 工厂方法?
how can I use an Objective-C factory method in a superclass, when instantiating a subclass?
这个问题是关于 subclassing 一个有工厂方法的 class。我无法让 subclass 正常工作。
我有一辆 class 车。我希望它 return 一个 Car 实例 只有 如果它能够进行指定距离的旅行,同时考虑到它的燃料消耗和燃料容量。我为此制作了一个 class (工厂)方法。
当我从我的视图控制器调用工厂方法来实例化汽车时,它完全符合我的要求(代码在下方显示)。
@interface Car : NSObject
@end
@implementation Car
- (instancetype) init
{ return [super init]; }
+ (Car *) carWithFuelConsumption:(double)miles_per_gallon
andGallonsInTank:(double)gallons
forTripLength:(double)miles_to_go
{
if (miles_per_gallon * gallons) > miles_to_go) {
Car *goodCar = [[self alloc] init];
return goodCar;
} else {
return nil;
}
现在我还需要卡车,为此我需要跟踪它们的载货量。我让 Truck 成为 Car 的子class。
@interface Truck : Car
@property (double) cargoCapacityLbs;
@end
@implementation Truck
- (instancetype) init {
self = [super init];
if (self) {
self.cargoCapacity= 2000.0;
}
return self;
}
在我的视图控制器中,我可以很好地实例化汽车:
Car *car1 = [Car carWith... 20 ...5 ... 60]; //5 gallons enough for 60 miles
Car *car2 = [Car carWith... 20 ...5 ... 90];
/// car2 is nil, 5 gallons NOT enough for 60 miles at 20 miles per gallon.
但是一辆卡车可以载我
A) 编译器警告
Truck *t1 = [Car carWith... 20 ...5 ... 60]; //5 gallons enough for 60 miles
**incompatible pointer types assigning to Truck from Car**
如果我将 Car 更改为 Truck,情况相同,如下所示:
Truck *truck1 = [Truck carWith... 20 ...5 ... 60]; //5 gallons enough for 60 miles
B) 并且在尝试访问 truck1.cargoCapacityLbs
时崩溃
cargoCapacityLbs ..unrecognized selector sent to instance <....>**
我认为关于子classing 有一些基本的东西我不理解。我试过在 Truck 初始化方法中直接调用工厂方法,没有成功。
我正在考虑重写 Car class,不使用工厂方法,但这似乎很糟糕,因为这样就无法在 Car class 中完成验证,并且会在视图控制器中完成。
有什么建议吗?
A) 您使用工厂方法的方法是合法的,应该可以正常工作。
要消除编译器警告,请在工厂方法声明中使用 instancetype
作为结果类型:
+ (instancetype) carWithFuelConsumption:(double)miles_per_gallon
andGallonsInTank:(double)gallons
forTripLength:(double)miles_to_go;
B) 从上面的代码中,您应该能够访问 cargoCapacityLbs
而不会崩溃(也许您只是拼错了名字?)。这是我使用过的代码,它运行正常:
@interface Car : NSObject
+ (instancetype) carWithFuelConsumption:(double)miles_per_gallon
andGallonsInTank:(double)gallons
forTripLength:(double)miles_to_go;
@end
@implementation Car
+ (instancetype) carWithFuelConsumption:(double)miles_per_gallon
andGallonsInTank:(double)gallons
forTripLength:(double)miles_to_go
{
if(miles_per_gallon * gallons > miles_to_go) {
Car *goodCar = [[self alloc] init];
return goodCar;
} else {
return nil;
}
}
@end
@interface Truck : Car
@property double cargoCapacityLbs;
@end
@implementation Truck
- (instancetype) init {
self = [super init];
if (self) {
self.cargoCapacityLbs = 2000.0;
}
return self;
}
@end
Truck* t1 = [Truck carWithFuelConsumption:5 andGallonsInTank:44 forTripLength:3];
NSLog(@"%f", t1.cargoCapacityLbs);
实例类型做到了。但是我对
不是很满意
Car *goodCar = [[self alloc] init];
在工厂方法中。
我也看到了这个博客post
http://ernstsson.net/post/80915338055/objective-c-class-factory-methods
所以我换了车:
@interface Car
@property double burn;
@property double gallons;
@end
@implementation Car
- (instancetype) init {
return nil;
///preclude use of an incomplete initializer
}
- (instancetype) initWithBurn:(double)MPG andGallonsInTank:(double) gallons {
self = [super init];
if (self) {
_burn = MPG;
_gallons = gallons;
}
return self;
}
+ (instancetype) createWithFuelConsumption:(double)MPG andGallonsInTank:(double)Gallons forTripLength:(double) miles {
if (MPG * Gallons < miles) {
return nil;
} else {
return [[self alloc] initWithBurn:MPG andGallonsInTank:Gallons];
}
}
现在工厂方法中不再引用 Car class。
(不能post这作为评论,它太长了)
这个问题是关于 subclassing 一个有工厂方法的 class。我无法让 subclass 正常工作。
我有一辆 class 车。我希望它 return 一个 Car 实例 只有 如果它能够进行指定距离的旅行,同时考虑到它的燃料消耗和燃料容量。我为此制作了一个 class (工厂)方法。
当我从我的视图控制器调用工厂方法来实例化汽车时,它完全符合我的要求(代码在下方显示)。
@interface Car : NSObject
@end
@implementation Car
- (instancetype) init
{ return [super init]; }
+ (Car *) carWithFuelConsumption:(double)miles_per_gallon
andGallonsInTank:(double)gallons
forTripLength:(double)miles_to_go
{
if (miles_per_gallon * gallons) > miles_to_go) {
Car *goodCar = [[self alloc] init];
return goodCar;
} else {
return nil;
}
现在我还需要卡车,为此我需要跟踪它们的载货量。我让 Truck 成为 Car 的子class。
@interface Truck : Car
@property (double) cargoCapacityLbs;
@end
@implementation Truck
- (instancetype) init {
self = [super init];
if (self) {
self.cargoCapacity= 2000.0;
}
return self;
}
在我的视图控制器中,我可以很好地实例化汽车:
Car *car1 = [Car carWith... 20 ...5 ... 60]; //5 gallons enough for 60 miles
Car *car2 = [Car carWith... 20 ...5 ... 90];
/// car2 is nil, 5 gallons NOT enough for 60 miles at 20 miles per gallon.
但是一辆卡车可以载我
A) 编译器警告
Truck *t1 = [Car carWith... 20 ...5 ... 60]; //5 gallons enough for 60 miles
**incompatible pointer types assigning to Truck from Car**
如果我将 Car 更改为 Truck,情况相同,如下所示:
Truck *truck1 = [Truck carWith... 20 ...5 ... 60]; //5 gallons enough for 60 miles
B) 并且在尝试访问 truck1.cargoCapacityLbs
时崩溃cargoCapacityLbs ..unrecognized selector sent to instance <....>**
我认为关于子classing 有一些基本的东西我不理解。我试过在 Truck 初始化方法中直接调用工厂方法,没有成功。
我正在考虑重写 Car class,不使用工厂方法,但这似乎很糟糕,因为这样就无法在 Car class 中完成验证,并且会在视图控制器中完成。
有什么建议吗?
A) 您使用工厂方法的方法是合法的,应该可以正常工作。
要消除编译器警告,请在工厂方法声明中使用 instancetype
作为结果类型:
+ (instancetype) carWithFuelConsumption:(double)miles_per_gallon
andGallonsInTank:(double)gallons
forTripLength:(double)miles_to_go;
B) 从上面的代码中,您应该能够访问 cargoCapacityLbs
而不会崩溃(也许您只是拼错了名字?)。这是我使用过的代码,它运行正常:
@interface Car : NSObject
+ (instancetype) carWithFuelConsumption:(double)miles_per_gallon
andGallonsInTank:(double)gallons
forTripLength:(double)miles_to_go;
@end
@implementation Car
+ (instancetype) carWithFuelConsumption:(double)miles_per_gallon
andGallonsInTank:(double)gallons
forTripLength:(double)miles_to_go
{
if(miles_per_gallon * gallons > miles_to_go) {
Car *goodCar = [[self alloc] init];
return goodCar;
} else {
return nil;
}
}
@end
@interface Truck : Car
@property double cargoCapacityLbs;
@end
@implementation Truck
- (instancetype) init {
self = [super init];
if (self) {
self.cargoCapacityLbs = 2000.0;
}
return self;
}
@end
Truck* t1 = [Truck carWithFuelConsumption:5 andGallonsInTank:44 forTripLength:3];
NSLog(@"%f", t1.cargoCapacityLbs);
实例类型做到了。但是我对
不是很满意 Car *goodCar = [[self alloc] init];
在工厂方法中。
我也看到了这个博客post http://ernstsson.net/post/80915338055/objective-c-class-factory-methods
所以我换了车:
@interface Car
@property double burn;
@property double gallons;
@end
@implementation Car
- (instancetype) init {
return nil;
///preclude use of an incomplete initializer
}
- (instancetype) initWithBurn:(double)MPG andGallonsInTank:(double) gallons {
self = [super init];
if (self) {
_burn = MPG;
_gallons = gallons;
}
return self;
}
+ (instancetype) createWithFuelConsumption:(double)MPG andGallonsInTank:(double)Gallons forTripLength:(double) miles {
if (MPG * Gallons < miles) {
return nil;
} else {
return [[self alloc] initWithBurn:MPG andGallonsInTank:Gallons];
}
}
现在工厂方法中不再引用 Car class。
(不能post这作为评论,它太长了)