实例化子类时,如何在超类中使用 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这作为评论,它太长了)