Objective-C“消息” - 正确的阅读方式是什么?

发布于 2024-08-09 22:54:12 字数 1076 浏览 7 评论 0原文

基本上,您可以在 Objective-C 中声明一个方法,并将每个参数命名两次

我知道这很强大,但我不太确定如何使用它...

当 John Greets Kelly 时:

[ p Greet:"John" toPerson:"Kelly"greetWith:"hey babe" ] ;

它的某些内容读起来不自然。我不确定经验丰富的 Objective-C 程序员是否会这样写“消息”。

有人可以解释每个参数有两个名称的原因,并可能提供一个更有用的示例来说明如何有效地使用它来在程序中赋予含义吗?

还有一点让我困扰,那就是第一个参数的名称与“消息”的名称基本相同。您如何通过编写有意义且易于理解的方法/“消息名称”来解决这个问题?

#import <Foundation/Foundation.h>

@interface Person : NSObject
{
}

-(void)Greet:(char*)from toPerson:(char*)to greetWith:(char*)greeting ;

@end

@implementation Person

-(void)Greet:(char*)from toPerson:(char*)to greetWith:(char*)greeting ;
{
  printf( "%s says %s to %s\n", from, greeting, to ) ;
}

@end



int main (int argc, const char * argv[])
{
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];


  Person * p = [ Person alloc ] ;

  [ p Greet:"John" toPerson:"Kelly" greetWith:"hey babe" ] ;
  [ p Greet:"Kelly" toPerson:"John" greetWith:"get bent" ] ;

  [ p release ] ;



  [pool drain];
  return 0;
}

You can declare a method in objective-c and name each parameter twice, basically.

I get the idea that this is powerful, but I'm not quite sure how to use it yet...

When John Greets Kelly:

[ p Greet:"John" toPerson:"Kelly" greetWith:"hey babe" ] ;

Something about it doesn't read naturally. I'm not sure if that's how an experienced objective-c programmer would write that "message".

Can someone explain the reason for two names for each parameter and possibly a more useful example of how this can be used effectively to put meaning in the program?

Also something bothers me and that is the name of the first parameter is basically the same as the name of the 'message'. How do you resolve that in writing meaningful and understandable method/'message names'?

#import <Foundation/Foundation.h>

@interface Person : NSObject
{
}

-(void)Greet:(char*)from toPerson:(char*)to greetWith:(char*)greeting ;

@end

@implementation Person

-(void)Greet:(char*)from toPerson:(char*)to greetWith:(char*)greeting ;
{
  printf( "%s says %s to %s\n", from, greeting, to ) ;
}

@end



int main (int argc, const char * argv[])
{
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];


  Person * p = [ Person alloc ] ;

  [ p Greet:"John" toPerson:"Kelly" greetWith:"hey babe" ] ;
  [ p Greet:"Kelly" toPerson:"John" greetWith:"get bent" ] ;

  [ p release ] ;



  [pool drain];
  return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

无声情话 2024-08-16 22:54:12

首先要做的事情:作为风格注释,将大括号放在一起:

[ Person alloc ]

应该是

[Person alloc]

我还注意到您在分配 Person 时忘记初始化 Person,您应该使用:

Person *p = [[Person alloc] init];

了解如何声明方法需要一点时间。检查框架如何命名其方法是有用的。对于你的具体例子,我认为你过度设计了。您正在寻找这样的内容:

Person *john = [[Person alloc] initWithName:@"John"];
Person *kelly = [[Person alloc] initWithName:@"Kelly"];

[john greetPerson:kelly withGreeting:@"Hey babe."];
[kelly greetPerson:john withGreeting:@"Get bent."];

请注意,我也没有将 greetPerson 中的 g 大写。这是 Objective-C 的风格约定。

不要忘记,一个对象有自己的身份,因此在与某人交谈之前,您很少需要指示一个对象(旨在代表一个人)它是谁。当您写消息时,读起来应该像英语。当你陷入多个争论时——诚然,很少见——开始用逗号思考:

[john sendEmailToPerson:kelly withSubject:subject body:body attachments:nil];

看看这是如何进行的?即使这还有一些不足之处,我也还没有掌握这一点。给它时间。

Apple 的 Cocoa 编码指南< /a>.


另外,让自己摆脱 C 陷阱。这是我编写整个程序的方式(我正在介绍大量概念,所以不要指望理解所有内容):

#import <Foundation/Foundation.h>

@interface Person : NSObject {
    NSString *name;
}

@property (copy) NSString *name;

- (id)init;
- (id)initWithName:(NSString *)nm;
- (void)greetPerson:(Person *)who withGreeting:(NSString *)grt;

@end

@implementation Person
@synthesize name;

- (id)init {
    if (self = [super init]) {
        name = @"James Bond";          // not necessary, but default
    }                                  // values don't hurt.
    return self;
}
- (id)initWithName:(NSString *)nm {
    if (self = [self init]) {
       name = [nm copy];
    }
    return self;
}

- (void)greetPerson:(Person *)who withGreeting:(NSString *)grt {
    NSLog(@"%@ says '%@' to %@", self.name, grt, who.name);
}

- (void)dealloc {
    [name release];
    [super dealloc];
}

@end

int main(int argc, const char * argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    Person *john = [[Person alloc] initWithName:@"John"];
    Person *kelly = [[Person alloc] initWithName:@"Kelly"];

    [john greetPerson:kelly withGreeting:@"StackOverflow is great, isn't it?"];
    [kelly greetPerson:john withGreeting:@"Weren't we supposed to flirt?"];

    [john release];
    [kelly release];

    [pool drain];
    return 0;
}

这段代码完全未经测试,所以如果它运行顺利,我会留下深刻的印象。

First things first: as a stylistic note, bring your braces together:

[ Person alloc ]

should be

[Person alloc]

I also note that you're forgetting to initialize Person when you alloc it, you should be using:

Person *p = [[Person alloc] init];

Getting the feel for how to declare methods takes a little bit of time. Examining how the framework names its methods is useful. For your specific example, I think you're overengineering. You're looking for something like this:

Person *john = [[Person alloc] initWithName:@"John"];
Person *kelly = [[Person alloc] initWithName:@"Kelly"];

[john greetPerson:kelly withGreeting:@"Hey babe."];
[kelly greetPerson:john withGreeting:@"Get bent."];

Notice that I've not capitalized the g in greetPerson, either. That's a stylistic convention of Objective-C.

Don't forget that an object has its own identity, so rarely do you need to instruct an object (meant to represent a person) who it is before it talks to someone. When you write a message, it should read like English. When you get into multiple arguments -- admittedly, rare -- start thinking with commas:

[john sendEmailToPerson:kelly withSubject:subject body:body attachments:nil];

See how that flows? And even that leaves some to be desired, I don't have this mastered yet either. Give it time.

A very useful document on this is Apple's Coding Guidelines for Cocoa.


Also, get yourself out of the C trap. Here's how I'd write your entire program (I'm introducing a boatload of concepts, so don't expect to understand all of it):

#import <Foundation/Foundation.h>

@interface Person : NSObject {
    NSString *name;
}

@property (copy) NSString *name;

- (id)init;
- (id)initWithName:(NSString *)nm;
- (void)greetPerson:(Person *)who withGreeting:(NSString *)grt;

@end

@implementation Person
@synthesize name;

- (id)init {
    if (self = [super init]) {
        name = @"James Bond";          // not necessary, but default
    }                                  // values don't hurt.
    return self;
}
- (id)initWithName:(NSString *)nm {
    if (self = [self init]) {
       name = [nm copy];
    }
    return self;
}

- (void)greetPerson:(Person *)who withGreeting:(NSString *)grt {
    NSLog(@"%@ says '%@' to %@", self.name, grt, who.name);
}

- (void)dealloc {
    [name release];
    [super dealloc];
}

@end

int main(int argc, const char * argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    Person *john = [[Person alloc] initWithName:@"John"];
    Person *kelly = [[Person alloc] initWithName:@"Kelly"];

    [john greetPerson:kelly withGreeting:@"StackOverflow is great, isn't it?"];
    [kelly greetPerson:john withGreeting:@"Weren't we supposed to flirt?"];

    [john release];
    [kelly release];

    [pool drain];
    return 0;
}

This code is completely untested, so if it works without a hitch I'll be duly impressed.

李不 2024-08-16 22:54:12

其他人已经涵盖了最重要的要点,所以我将权衡一些补充问题:

还有一点让我困扰,那就是第一个参数的名称基本上与“消息”的名称相同。您如何通过编写有意义且易于理解的方法/“消息名称”来解决这个问题?

处理此问题的最常见方法是使方法名称由“它是什么/做什么”和第一个参数的标签组合而成。例子:

 NSColor * color = [NSColor colorWithDeviceRed:0.5 green:0.5 blue:0.5 alpha:0.5];

有人可以解释一下每个参数有两个名称的原因,并可能提供一个更有用的示例来说明如何有效地使用它来在程序中赋予含义吗?

简单的回答是,这两个名字是针对不同的受众的。一个是该方法的使用者,另一个是该方法的作者。再次考虑上面的例子。方法声明如下所示:

+ (NSColor *)colorWithDeviceRed:(CGFloat)red
                          green:(CGFloat)green
                           blue:(CGFloat)blue
                          alpha:(CGFloat)alpha

当用户调用该方法时,他们关心第一个标签(冒号之前的标签)。您可以在我的第一个示例中看到,其中通道值作为数字常量传递,在代码中只能看到标签。

实际参数名称(类型后面的部分)在方法定义中使用,因此实际上仅适用于编写方法的程序员,因为这些是可用的变量在方法体本身内。

Other people have covered the most important points, so I'll just weigh in on some of the supplementary questions:

Also something bothers me and that is the name of the first parameter is basically the same as the name of the 'message'. How do you resolve that in writing meaningful and understandable method/'message names'?

The most common way of dealing with this is to make the method name a combination of "what it is/does" and the label for the first parameter. Example:

 NSColor * color = [NSColor colorWithDeviceRed:0.5 green:0.5 blue:0.5 alpha:0.5];

Can someone explain the reason for two names for each parameter and possibly a more useful example of how this can be used effectively to put meaning in the program?

The quick answer is that the two names are intended for different audiences; one is for the user of the method, the other is for the author of the method. Consider the above example again. The method declaration looks like this:

+ (NSColor *)colorWithDeviceRed:(CGFloat)red
                          green:(CGFloat)green
                           blue:(CGFloat)blue
                          alpha:(CGFloat)alpha

When a user calls that method, they are concerned with the first labels (the ones before the colon). You can see in my first example, where the channel values are passed as numeric constants, that only the labels are seen in code.

The actual parameter names (the parts after the type), are used within the method definition, and as such are really only there for the programmer who writes the method, since those are the variables that will be available within the method body itself.

惟欲睡 2024-08-16 22:54:12

该方法的第一个“部分”是选择器,对于您的示例,这包括-greet:toPerson:greetWith:,这是该方法的实际名称。

第二个“部分”是方法的参数,在您的示例中,它们是问候语。

这类似于 C 语言,

int greet(string to, string greeting) {
    print(greeting, to);
}

我还应该提到,您可能想要使用 NSString * 而不是 char *NSLog() 而不是 printf() (不用担心,它的工作原理几乎完全相同)。

The first "part" of the method is the selector, for your example this includes -greet:toPerson:greetWith:, this is the actual name of the method.

The second "part" are the parameters of the method, in your example they are to, greeting.

This is akin to something like C where you would have

int greet(string to, string greeting) {
    print(greeting, to);
}

I should also mention, you're likely going to want to work with NSString * instead of char * and NSLog() instead of printf() (don't worry, it works almost exactly the same).

若无相欠,怎会相见 2024-08-16 22:54:12

可能是这样:

[personJohn greetPerson:@"Kelly" withGreeting:@"hey babe"];

person 对象已经是 John,并且他正在问候另一个 person 对象,我不会像您那样将其定义为字符串,而是作为 Person 类的另一个实例,然后您可以执行 greetWithString

[personJohn greetPerson:personKelly withGreeting:@"hey babe"];

您没有两次定义参数,这就是您感到困惑的地方。如果您了解 C++,您通常会使用:

void greetPerson(Person thePerson, string greeting);

作为函数原型。然后你可以这样称呼它:

greetPerson(personKelly, "hey babe");

现在,objective-c 所做的一切就是通过自我记录来让你变得更容易。您不是简单地将参数放入函数,而是在声明它们之前命名它们,因此上面的调用将是:

greetPerson(Person:personKelly, greeting:"hey babe");

给定上面发布的函数原型。这样,当您阅读代码时,您就知道每个参数在做什么,因此是自我记录的。乍一看似乎很乏味,但代码的可读性大大提高了。

Probably it'd be:

[personJohn greetPerson:@"Kelly" withGreeting:@"hey babe"];

The person object is already John and he's greeting another person object, which I wouldn't define as a string as you did, but instead as another instance of class Person, and then you could do greetWithString.

[personJohn greetPerson:personKelly withGreeting:@"hey babe"];

You're not defining the parameters twice, that's where you're confused. If you know C++, you usually have:

void greetPerson(Person thePerson, string greeting);

as the function prototype for example. Then you would call it like so:

greetPerson(personKelly, "hey babe");

Now, all objective-c is doing is making it easy on you by being self-documenting. Instead of simply putting the parameters to the functions, you name them before you state them, so the above call would be:

greetPerson(Person:personKelly, greeting:"hey babe");

given the function prototype posted above. This way when you read the code, you know what each parameter is doing, hence being self documenting. It might seem tedious at first, but code readability is greatly increased.

忆离笙 2024-08-16 22:54:12

您上面描述的方法的名称是“Greet:toPerson:greetWith:”。冒号是名称的一部分。参数(及其类型说明符)则不然。

风格注释:不要以大写字符开头方法名称,除非您引用的是首字母缩略词(例如“URL”)。

The name of the method you describe above is "Greet:toPerson:greetWith:". The colons are part of the name. The parameters (and their type specifiers) are not.

Style note: don't start a method name with an uppercase character unless you're referring to an acronym (like "URL".)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文