Iphone @private变量/属性的正确使用

Iphone @private变量/属性的正确使用,iphone,objective-c,instance-variables,private-members,Iphone,Objective C,Instance Variables,Private Members,我所有的研究都表明,@private指令没有真正的用法-所以我肯定遗漏了什么,需要各位专家插话:-) 假设我们有两个类:汽车类和跑车类,其中跑车是汽车的子类 这是汽车课程: @interface Car : NSObject { NSString *make; NSString *model; @private int numberOfBackSeatPassengers; // I'm making this a private iVar cause I'm

我所有的研究都表明,@private指令没有真正的用法-所以我肯定遗漏了什么,需要各位专家插话:-)

假设我们有两个类:汽车类和跑车类,其中跑车汽车的子类

这是汽车课程:

@interface Car : NSObject {
    NSString *make;
    NSString *model;

    @private
    int numberOfBackSeatPassengers;  // I'm making this a private iVar cause I'm just gonna
                // say that all Sportscars will be 2-seaters and therefore shouldn't
                // be able to set/get the number of back-seat passengers
}

@property (nonatomic, strong) NSString *make, *model;

// Now here's my first issue: if I also make "numberOfBackSeatPassengers" an @property 
// then it seems like all subclasses of this Car class *WILL* be able to access it as 
// well - even though I declared it as @private - but I'll do this anyway to make my point:

@property int numberOfBackSeatPassengers;

@end
#import "Car.h"

@interface Sportscar : Car

@property int turboEngineSize;

@end
实现如下所示:

@implementation Car

@synthesize make, model, numberOfBackSeatPassengers;

@end
-(void) setNumberOfBackSeatPassengers:(int)numPassgeners {
    numberOfBackSeatPassengers = numPassgeners;
}

-(int)numberOfBackSeatPassengers {
    return numberOfBackSeatPassengers;
}
现在是跑车课程:

@interface Car : NSObject {
    NSString *make;
    NSString *model;

    @private
    int numberOfBackSeatPassengers;  // I'm making this a private iVar cause I'm just gonna
                // say that all Sportscars will be 2-seaters and therefore shouldn't
                // be able to set/get the number of back-seat passengers
}

@property (nonatomic, strong) NSString *make, *model;

// Now here's my first issue: if I also make "numberOfBackSeatPassengers" an @property 
// then it seems like all subclasses of this Car class *WILL* be able to access it as 
// well - even though I declared it as @private - but I'll do this anyway to make my point:

@property int numberOfBackSeatPassengers;

@end
#import "Car.h"

@interface Sportscar : Car

@property int turboEngineSize;

@end
及其实施:

#import "Sportscar.h"

@implementation Sportscar

@synthesize turboEngineSize;

@end
在“主要”中,我有:

    Car *car1 = [[Car alloc] init];
    [car1 setMake:@"Chevy"];
    [car1 setModel:@"Impala"];
    [car1 setNumberOfBackSeatPassengers:3];

    Sportscar *sports1 = [[Sportscar alloc] init];
    [sports1 setMake:@"Audi"];
    [sports1 setModel:@"tt"];
    [sports1 setNumberOfBackSeatPassengers:3];
显然,我能够在跑车上设置后座乘客数,尽管iVar被声明为@private,但这是因为我在“Car.h”中将其设置为@属性,这意味着它的合成getter和setter是实例方法,因此可供汽车的所有子类使用

另一个选项是不要在“Car.h”中将numberOfBackseatPassentials声明为@property,将其作为一个简单的iVar保存在那里,而是在@implementation“Car.m”中手动为其创建一个Setter和Getter,如下所示:

@implementation Car

@synthesize make, model, numberOfBackSeatPassengers;

@end
-(void) setNumberOfBackSeatPassengers:(int)numPassgeners {
    numberOfBackSeatPassengers = numPassgeners;
}

-(int)numberOfBackSeatPassengers {
    return numberOfBackSeatPassengers;
}
这将使得NumberOfBackseatPasswords的getter和setter只能在“Car.m”中使用,我想这将使他们成为“private”,但他们也将私有化:我不能从Main或“Car.m”之外的任何地方给他们打电话,这是真正的要点:这样做意味着“Car.h”中的@private指令在任何情况下都不会真正起作用。我的意思是,我现在可以回到“Car.h”,去掉那里的“@private”指令——我的后座乘客数量的手动设置器和获取器仍然可以像现在一样工作,被认为是私密的-那么“@private”有什么好处呢?它是如何真正发挥作用的

有人能真正弄清楚这件事吗

(是的,我知道我可以在“Car.m”文件的@interface部分扩展我的Car类-通过一个类别,或者先将numberOfBackseatPassators设置为只读属性,然后将其更改为readwrite,等等-但这些似乎都像是使“@private”变为“private”的变通方法或“hacks”工作。我只是不明白@private是如何独立工作的。)

=====================================================

编辑-回应aroth的以下评论:

1) aroth说子类理论上仍然可以调用未在其父类头中声明的方法是绝对正确的——通过使用
performSelector
。我说“理论上”,因为在我的情况下,它不完全正确工作:如果在“主要”-我调用

[sportscar1 performSelector:@selector(SetNumberOfBackseatPassentials:)]

然后,我为
numberOfBackseatPassentials
插入了一些垃圾号,因为这样调用该方法时,我无法显式地将数字作为参数传递

(问题:有办法解决吗?)

2) aroth说的也完全正确,在
跑车中
我们可以简单地覆盖
汽车
类的设置器和获取器,用于
后座乘客的数量
,并让这些覆盖方法将其重置为0,或给出一个错误,等等。虽然这是一个非常实用的解决方案,似乎解决了这个特殊的问题,但我觉得它没有解决更大的问题,即
@private
似乎没有真正做到它应该做的事情

3) 重新设计逻辑,为
FourDoorCar
创建一个类,为
twooorcar
创建另一个类,然后在此基础上继续构建,这是一个有趣的选择-但现在感觉Objective-C的语法几乎是“强制的”这一切都取决于我的编程逻辑和我如何构建我的项目——这感觉像是一种强加。也许我是错的,我做的太多了——但不管怎样,这一切都是因为
@private
没有做它似乎承诺的事情。。。?感觉不对

一天结束时,我总是回到同一个问题:
@private
实际上对我们有什么好处?它有什么好处,它“买”了我什么?似乎如果我想让一个iVar是私有的,我可以在“.m”文件中声明它,而不必首先在头文件中声明它。我是说我说的对不对?或者在某些情况下,您希望在头中声明一个iVar为
@private
,但不在头中声明它的setter和getter,这样子类就不会显式地使用它们了,并且所有这些都有意义吗

我们能想出一个实际的例子吗?是否有某种类型的汽车财产,我想在标题中声明为
@private
(与“.m”相反),这对我有好处? 我认为
numberofBackseatPassentials
将是一个很好的例子,但我不知道它在实际代码中是如何工作的

=========================================================================

编辑#2-继续与@aroth:-)对话

@aroth—我完全同意,在头中声明所有IVAR更好/更有组织性,而不是将内容拆分,以便有些在头中,有些在实现中。这造成了混乱,我真的不喜欢这种方法。(我在最初的问题中指出,我不想使用实现和/或分类方法来解决我的问题。) -此外,是的,属性绝对不必总是由IVAR进行备份

-关于恰当地设计类,我同意这当然是良好编程的关键。汽车/跑车的例子是我在现场编造的,以给出我的答案