Objective c 目标C-接受者,即接受者/接受者
我已经广泛地阅读了已经发布的问题,并没有找到我想要的答案 我完全理解使用Objective c 目标C-接受者,即接受者/接受者,objective-c,Objective C,我已经广泛地阅读了已经发布的问题,并没有找到我想要的答案 我完全理解使用@syntesize指令创建getter和setter方法的概念(即,如果我有@property int-width和@synthetic-width,我无意中创建了width的getter方法和setWidth:的setter方法) 但是,当我没有使用@synthesis指令,而是在@implementation部分声明作为对象的实例变量时,我并不完全理解访问器方法是如何工作的。这是我对以下代码不了解的地方: 1) 在ma
@syntesize
指令创建getter和setter方法的概念(即,如果我有@property int-width
和@synthetic-width
,我无意中创建了width
的getter方法和setWidth:
的setter方法)
但是,当我没有使用@synthesis
指令,而是在@implementation
部分声明作为对象的实例变量时,我并不完全理解访问器方法是如何工作的。这是我对以下代码不了解的地方:
1) 在main
中显示:
NSLog(@"Origin at (%i, %i)", myRect.origin1.x, myRect.origin1.y);
在我看来,它似乎将调用[[myRect origin1]x]
方法,该方法首先确定[myRect origin1]
返回原点
,然后立即调用[origin x]
(然后对y
执行相同操作)。现在,让我感到不安的是,如果我要更改getter方法的名称
-(XYpoint *) origin1;
包含在矩形中。h到
-(XYpoint *) origin2;
程序出现大量错误并停止编译。注意:我还在引用该方法的任何地方都更改了该方法的名称,包括将main中前面的代码更改为
NSLog(@"Origin at (%i, %i)", myRect.origin2.x, myRect.origin2.y);
但是,如果我还将setter方法的名称从:
-(void) setOrigin1: (XYpoint *) pt
致:
然后一切都像以前一样工作。在我看来,只有当getter和setter都在x
setX
命名约定中命名时,它才能正常工作。我想这主要是我需要解释的:
A) 如果我创建的实例变量恰好是一个对象(如本例中的“origin”),那么我必须为它创建getter和setter方法吗
B) 我可以创建一个getter方法而不是setter方法吗
C) 如果我为“origin”创建了getter和setter方法,则必须以x
setX
的方式对它们进行命名。在本例中为-(XYpoint*)origin1
和-(void)setOrigin1:(XYpoint*)pt
。如果我更改了getter的名称,我必须相应地更改setter的名称
以下是所有代码:
矩形。h:
#import <Foundation/Foundation.h>
@class XYpoint;
@interface Rectangle : NSObject
@property int width, height;
-(XYpoint *) origin1;
-(void) setOrigin1: (XYpoint *) pt;
-(void) setWidth: (int) w andHeight: (int) h;
-(int) area;
-(int) perimeter;
@end
XYpoint.h:
#import <Foundation/Foundation.h>
@interface XYpoint : NSObject
@property int x, y;
-(void) setX: (int) xVal andY: (int) yVal;
@end
main.m:
#import <Foundation/Foundation.h>
#import "Rectangle.h"
#import "XYpoint.h"
int main (int argc, const char * argv[])
{
@autoreleasepool {
Rectangle *myRect = [[Rectangle alloc] init];
XYpoint *myPoint = [[XYpoint alloc] init];
[myPoint setX: 100 andY: 200];
[myRect setWidth: 5 andHeight:8];
myRect.origin1 = myPoint;
NSLog(@"Rectangle w = %i, h = %i", myRect.width, myRect.height);
NSLog(@"Origin at (%i, %i)", myRect.origin1.x, myRect.origin1.y);
NSLog(@"Area = %i, Perimeter = %i", [myRect area], [myRect perimeter]);
}
return 0;
}
#导入
#导入“Rectangle.h”
#导入“XYpoint.h”
int main(int argc,const char*argv[]
{
@自动释放池{
矩形*myRect=[[Rectangle alloc]init];
XYpoint*myPoint=[[XYpoint alloc]init];
[myPoint setX:100 andY:200];
[myRect setWidth:5,height:8];
myRect.origin1=myPoint;
NSLog(@“矩形w=%i,h=%i”,myRect.width,myRect.height);
NSLog(@“原点在(%i,%i)”,myRect.origin1.x,myRect.origin1.y);
NSLog(@“面积=%i,周长=%i”,[myRect面积],[myRect周长];
}
返回0;
}
您很可能忘记更改头文件或实现文件中的方法名称。拥有只读属性(没有setter方法)是完全有效的
如果要使用点表示法(即myRect.origin1)访问对象属性,最好的做法是确保在头文件中定义相应的属性,即包括一行,例如:
@property(readonly) XYPoint *origin1; // for read only properties
@property(retain) XYPoint *origin1; // for read/write properties
即使不使用@synthesis
,也要使用它们,而不是头文件中的常规方法声明。这些行实际上并不创建getter和setter,它们只是通知编译器类具有这些属性。然后,编译器需要名为-origin1
和-setOrigin1
的getter(如果不使用readonly,则需要setter)。setter/getter的名称很重要(有关详细信息,请参阅苹果关于键值编码的文档)
您还应该了解Cocoa的内存管理准则:除非使用自动引用计数,否则矩形类负责在setter中保留或复制XYPoint对象。[编辑]:我刚刚意识到您显然在使用ARC,因为您使用了@autoreleasepool
语法
A) 如果我创建的实例变量恰好是一个对象(如
(本例中为“origin”)我必须为其创建getter和setter方法吗
不可以。如果声明属性,则需要提供自己的访问器或使用@synthesis指令来创建它们。但是您可以拥有所有您喜欢的实例变量,而无需访问它们
B) 我可以创建一个getter方法而不是setter方法吗
是的,如果您将属性声明为只读,则可以只提供getter
C) 如果我同时创建getter和setter方法,这是必须的吗
对于“origin”,它们都以x setX方式命名。在这个
大小写为-(XYpoint*)origin1和-(void)setOrigin1:(XYpoint*)pt。
如果我更改getter的名称,我必须更改getter的名称
塞特
您可以为访问器提供自己的名称,但如果您希望类与相关属性的键值编码兼容,则应遵循通常的约定:
@property (getter=isBar, setter=setBar) int bar;
通过电子邮件讨论后,我们发现这个问题实际上似乎是一个叮当声中的bug。考虑下面的迷你程序:
#import <Foundation/Foundation.h>
@interface TestObject : NSObject
-(void)setIdVar:(id)someId;
@end
@implementation TestObject
-(void)setIdVar:(id)someId;
{
NSLog(@"-setIdVar called with argument: %@", someId);
}
@end
int main (int argc, const char * argv[])
{
@autoreleasepool {
TestObject *testObj = [[TestObject alloc] init];
testObj.idVar = @"test";
}
return 0;
}
#导入
@接口测试对象:NSObject
-(void)setIdVar:(id)someId;
@结束
@实现测试对象
-(void)setIdVar:(id)someId;
{
NSLog(@“-setIdVar,用参数%@”调用,someId);
}
@结束
int main(int argc,const char*argv[]
{
@自动释放池{
TestObject*testObj=[[TestObject alloc]init];
testObj.idVar=@“测试”;
}
返回0;
}
显然,我们希望这个程序运行并输出-setIdVar,并使用参数test调用。这正是编译时发生的情况
@property(readonly) XYPoint *origin1; // for read only properties
@property(retain) XYPoint *origin1; // for read/write properties
@property (getter=isBar, setter=setBar) int bar;
#import <Foundation/Foundation.h>
@interface TestObject : NSObject
-(void)setIdVar:(id)someId;
@end
@implementation TestObject
-(void)setIdVar:(id)someId;
{
NSLog(@"-setIdVar called with argument: %@", someId);
}
@end
int main (int argc, const char * argv[])
{
@autoreleasepool {
TestObject *testObj = [[TestObject alloc] init];
testObj.idVar = @"test";
}
return 0;
}