Objective-C“私有”方法的命名约定是什么?

时间:2021-08-28 13:23:18

Inheriting code from other developers has made me a firm believer in keeping as many messages as possible out of a class' public interface by means of a Class Extension. I'm also a firm believer in adopting special naming conventions for private, implementation-specific members of a class. I really like being able to tell at a glance what messages being sent and what members being referenced within the implementation context are not ever intended for public use and vice versa. If nothing else, it makes the overall semantics of a class easier for me grasp more quickly, and that's worth it.

继承其他开发人员的代码使我坚信通过类扩展从类的公共接口中保留尽可能多的消息。我也坚信为类的特定于实现的私有成员采用特殊的命名约定。我真的希望能够一目了然地告诉我们发送的消息是什么,以及在实现环境中引用的成员是不是打算供公众使用,反之亦然。如果不出意外,它会让我更容易掌握一个班级的整体语义,这是值得的。

Justification aside, I've written boatloads of classes with boatloads2 of private methods, but I've never really come up with a pattern for naming that I really love (like I do the controversial ivar_ convention for ivars). Notable examples:

除了理由之外,我已经编写了一大堆带有私有方法的船载类,但我从来没有真正想出一个我真正喜欢的命名模式(就像我对ivars做有争议的ivar_惯例)。值得注意的例子:

@interface myClass()

// I like this, but as we all know, Apple has dibs on this one, 
// and method name collisions are nasty.
- (void)_myPrivateMessage;

// The suffix version promoted by Google for ivars doesn't really translate
// well to method names in Objective-C, because of the way the method
// signature can be broken into several parts.
- (void)doWork_; // That's okay...
- (void)doWork_:(id)work with_:(id)something; // That's just ugly and tedious...
- (void)doWork_:(id)work with_:(id)something and_:(id)another; // My eyes...

// This version is suggested by Apple, and has the benefit of being officially 
// recommended. Alas, I don't like it: The capital letter is ugly. I don't like 
// underscores in the middle of the name. Worst of all, I have to type three characters 
// before code-sense does anything more useful than inform me that I am typing.
- (void)BF_doWork;

@end

At this point, there are a kajillion different means by which I could mangle my private method names, but instead of making something up, I figured I would first take a poll for any popular conventions I may not be aware of. So, what have you used?

在这一点上,有一种不同的手段,我可​​以通过它来破坏我的私人方法名称,但我没有做出什么,我想我会首先对我可能不知道的任何流行惯例进行民意调查。那么,你用过什么?

7 个解决方案

#1


3  

I use two levels of private methods: slightly private and very private. Slightly private methods are methods which could become public, but currently aren't. They are usually convenience methods that I use internally, and I usually don't put in as much protection unless I decide to make it public. For very private methods, I ignore apple and use an underscore prefix. Since 99% of my code is in classes I create and I usually have prefixes on my class names, the chances of running into naming problems is small. When adding code to classes I didn't make, I rarely make private methods, but add a short prefix on the rare occasion that I do.

我使用两个级别的私有方法:略微私有和非常私密。稍微私密的方法是可以公开的方法,但目前不是。它们通常是我在内部使用的便捷方法,除非我决定公开,否则我通常不会提供太多保护。对于非常私密的方法,我忽略了apple并使用下划线前缀。由于99%的代码都在我创建的类中,并且我的类名通常都有前缀,因此遇到命名问题的可能性很小。将代码添加到我没有创建的类时,我很少使用私有方法,但在极少数情况下添加一个简短的前缀。

#2


9  

I don't distinguish private methods by name. Instead, I keep them out of the public interface by declaring them in the class extension portion of the .m file, thus:

我没有按名称区分私人方法。相反,我通过在.m文件的类扩展部分声明它们来使它们脱离公共接口,因此:

@interface MyClass ()
- (void)doWork;
@end

#3


7  

I use double underscore for my private methods:

我为我的私有方法使用双下划线:

- (void)__doSomethingPrivate;

It almost looks like the single underscore-syntax (good readable) and at the same time confirms to the Apple guides.

它几乎看起来像单个下划线语法(良好的可读性),同时向Apple指南确认。

#4


4  

I use a prefix, no underscore. The prefix is generally related to the name of the project in question. If you do use underscores, there's no need to have more than one.

我使用前缀,没有下划线。前缀通常与相关项目的名称相关。如果您确实使用下划线,则不需要多个下划线。

#5


1  

I prefix private methods with a 'p':

我在私有方法前加上'p':

  • (void) pDoWork;
  • (无效)pDoWork;
  • (void) pDoWork:(id)work with:(id)something;
  • (void)pDoWork:(id)使用:(id)某事;

Similarly, I use 's' for static (or class) methods:

同样,我使用's'表示静态(或类)方法:

  • (Universe*)sGet; // used to return singleton Universe object.
  • (译注*)sget操作; //用于返回singleton Universe对象。

Beyond naming conventions, I declare private methods in .m files instead of .h files.

除了命名约定之外,我在.m文件中声明私有方法而不是.h文件。

#6


1  

Using a fixed prefix will help to "hide" the method from the outside world but it won't prevent a method from being accidentally overridden. E.g. I once extended a class and I made a method:

使用固定前缀将有助于从外部世界“隐藏”该方法,但它不会阻止方法被意外覆盖。例如。我曾经扩展过一个类,我做了一个方法:

- (void)private_close
{
    // ...
}

The result was that the behavior of the class broke in horrible ways. But why? It turned out, the super class also had a method name private_close and I was accidentally overriding it without calling super! How should I know? No compiler warning!

结果是班级的行为以可怕的方式破裂。但为什么?事实证明,超级类也有一个方法名称private_close,我不小心覆盖了它而没有调用超级!我怎么知道?没有编译警告!

No matter if your prefix is _ or __ or p or private_, if it is always the same, you will end up with problems like this one.

无论您的前缀是_还是__还是p或private_,如果它始终相同,您最终会遇到类似这样的问题。

So I prefix private methods (and properties!) with a prefix that resembles the class name. Therefor I take the upper case letters of the class name to form the "private prefix":

因此,我使用类似于类名的前缀为私有方法(和属性!)添加前缀。因此,我使用类名的大写字母来形成“私有前缀”:

  • ComplexFileParser -> CFP
  • ComplexFileParser - > CFP
  • URLDownloadTask -> URLDT
  • URLDownloadTask - > URLDT
  • SessionController -> SC
  • SessionController - > SC

This is still not perfectly safe, yet it is very unlikely that a subclass with a different name has the same still the same private prefix.

这仍然不是完全安全的,但具有不同名称的子类不太可能具有相同的私有前缀。

Also when you do frameworks, you should prefix all classes and other symbols with a framework prefix (as Apple does with NS..., CF..., CA..., SC..., UI..., etc.) and thus this class prefix is part of the private prefix as well making collisions even less likely:

此外,当您执行框架时,您应该为所有类和其他符号添加前缀框架前缀(如Apple对NS ...,CF ...,CA ...,SC ...,UI ...等等。 )因此这个类前缀是私有前缀的一部分,以及更可能发生冲突:

  • Framework DecodingUtils.framework -> DU
    • Class ComplexFileDecoder in framework -> DUComplexFileDecoder
      • Private Prefix -> DUCFD
        • Private Method close -> - (void)DUCFD_close
        • 私有方法关闭 - > - (void)DUCFD_close
      • 私有前缀 - > DUCFD私有方法关闭 - > - (void)DUCFD_close
    • 框架中的类ComplexFileDecoder - > DUComplexFileDecoder私有前缀 - > DUCFD私有方法关闭 - > - (void)DUCFD_close
  • 框架DecodingUtils.framework - >框架中的DU类ComplexFileDecoder - > DUComplexFileDecoder私有前缀 - > DUCFD私有方法关闭 - > - (void)DUCFD_close

Alternatively append the prefix at the end of the fist method argument name, to get better auto-completion:

或者在第一个方法参数名称的末尾附加前缀,以获得更好的自动完成:

- (void)doSomethingWith:(Type1)var1 parameters:(Type2)var2

will become

会变成

- (void)doSomethingWith_DUCFD:(Type1)var1 parameters:(Type2)var2

or always only append it to the last parameter name:

或者始终只将它附加到最后一个参数名称:

- (void)doSomethingWith:(Type1)var1 parameters_DUCFD:(Type2)var2

or (now it gets really crazy) - add a fake dummy parameter just for naming:

或者(现在它真的很疯狂) - 添加一个假的伪参数只是为了命名:

- (void)doSomethingWith:(Type1)var1 parameters:(Type2)var2 DUCFD:(id)x

where x is actually never used in the method and you pass nil for it:

其中x实际上从未在方法中使用过,你为它传递了nil:

[self doSomethingWith:var1 parameters:var2 DUCFD:nil];

and as it will always be the same at the end, use a pre-processor macro:

并且因为它在最后总是相同,所以使用预处理器宏:

#define priv DUCFD:nil
#define PRIVATE DUCFD:nil

// ...

[self doSomethingWith:var1 parameters:var2 priv];
[self doSomethingWith:var1 parameters:var2 PRIVATE];

Prefix and suffixing works also with properties (and thus their ivar, getter/setter methods), the preproessor trick above won't, of course.

前缀和后缀也适用于属性(因此它们的ivar,getter / setter方法),当然前面的前导技巧也不会。

#7


0  

Regarding Apple recommendations. You might be interested in how Apple writes it's own code.

关于Apple的建议。您可能对Apple如何编写自己的代码感兴趣。

If you check private APIs you will see that they use underscores for private methods everywhere. Every peace of Obj-C code in iOS uses them. And in many cases those methods go through multiple iOS versions without refactoring or renaming which means it's not a temporary solution for them but rather a convention. In fact, there're three levels of private methods they use extensively - no underscore, single and double underscore.

如果您检查私有API,您会看到他们在任何地方都使用下划线作为私有方法。 iOS中每个Obj-C代码的和平使用它们。在许多情况下,这些方法经过多个iOS版本而无需重构或重命名,这意味着它不是一个临时解决方案,而是一个约定。实际上,他们广泛使用的是三种级别的私有方法 - 没有下划线,单下和双下划线。

As for other solutions like "private", class or project name prefixes - they don't use them at all. Just underscores.

至于其他解决方案,如“私人”,类或项目名称前缀 - 他们根本不使用它们。只是强调。

#1


3  

I use two levels of private methods: slightly private and very private. Slightly private methods are methods which could become public, but currently aren't. They are usually convenience methods that I use internally, and I usually don't put in as much protection unless I decide to make it public. For very private methods, I ignore apple and use an underscore prefix. Since 99% of my code is in classes I create and I usually have prefixes on my class names, the chances of running into naming problems is small. When adding code to classes I didn't make, I rarely make private methods, but add a short prefix on the rare occasion that I do.

我使用两个级别的私有方法:略微私有和非常私密。稍微私密的方法是可以公开的方法,但目前不是。它们通常是我在内部使用的便捷方法,除非我决定公开,否则我通常不会提供太多保护。对于非常私密的方法,我忽略了apple并使用下划线前缀。由于99%的代码都在我创建的类中,并且我的类名通常都有前缀,因此遇到命名问题的可能性很小。将代码添加到我没有创建的类时,我很少使用私有方法,但在极少数情况下添加一个简短的前缀。

#2


9  

I don't distinguish private methods by name. Instead, I keep them out of the public interface by declaring them in the class extension portion of the .m file, thus:

我没有按名称区分私人方法。相反,我通过在.m文件的类扩展部分声明它们来使它们脱离公共接口,因此:

@interface MyClass ()
- (void)doWork;
@end

#3


7  

I use double underscore for my private methods:

我为我的私有方法使用双下划线:

- (void)__doSomethingPrivate;

It almost looks like the single underscore-syntax (good readable) and at the same time confirms to the Apple guides.

它几乎看起来像单个下划线语法(良好的可读性),同时向Apple指南确认。

#4


4  

I use a prefix, no underscore. The prefix is generally related to the name of the project in question. If you do use underscores, there's no need to have more than one.

我使用前缀,没有下划线。前缀通常与相关项目的名称相关。如果您确实使用下划线,则不需要多个下划线。

#5


1  

I prefix private methods with a 'p':

我在私有方法前加上'p':

  • (void) pDoWork;
  • (无效)pDoWork;
  • (void) pDoWork:(id)work with:(id)something;
  • (void)pDoWork:(id)使用:(id)某事;

Similarly, I use 's' for static (or class) methods:

同样,我使用's'表示静态(或类)方法:

  • (Universe*)sGet; // used to return singleton Universe object.
  • (译注*)sget操作; //用于返回singleton Universe对象。

Beyond naming conventions, I declare private methods in .m files instead of .h files.

除了命名约定之外,我在.m文件中声明私有方法而不是.h文件。

#6


1  

Using a fixed prefix will help to "hide" the method from the outside world but it won't prevent a method from being accidentally overridden. E.g. I once extended a class and I made a method:

使用固定前缀将有助于从外部世界“隐藏”该方法,但它不会阻止方法被意外覆盖。例如。我曾经扩展过一个类,我做了一个方法:

- (void)private_close
{
    // ...
}

The result was that the behavior of the class broke in horrible ways. But why? It turned out, the super class also had a method name private_close and I was accidentally overriding it without calling super! How should I know? No compiler warning!

结果是班级的行为以可怕的方式破裂。但为什么?事实证明,超级类也有一个方法名称private_close,我不小心覆盖了它而没有调用超级!我怎么知道?没有编译警告!

No matter if your prefix is _ or __ or p or private_, if it is always the same, you will end up with problems like this one.

无论您的前缀是_还是__还是p或private_,如果它始终相同,您最终会遇到类似这样的问题。

So I prefix private methods (and properties!) with a prefix that resembles the class name. Therefor I take the upper case letters of the class name to form the "private prefix":

因此,我使用类似于类名的前缀为私有方法(和属性!)添加前缀。因此,我使用类名的大写字母来形成“私有前缀”:

  • ComplexFileParser -> CFP
  • ComplexFileParser - > CFP
  • URLDownloadTask -> URLDT
  • URLDownloadTask - > URLDT
  • SessionController -> SC
  • SessionController - > SC

This is still not perfectly safe, yet it is very unlikely that a subclass with a different name has the same still the same private prefix.

这仍然不是完全安全的,但具有不同名称的子类不太可能具有相同的私有前缀。

Also when you do frameworks, you should prefix all classes and other symbols with a framework prefix (as Apple does with NS..., CF..., CA..., SC..., UI..., etc.) and thus this class prefix is part of the private prefix as well making collisions even less likely:

此外,当您执行框架时,您应该为所有类和其他符号添加前缀框架前缀(如Apple对NS ...,CF ...,CA ...,SC ...,UI ...等等。 )因此这个类前缀是私有前缀的一部分,以及更可能发生冲突:

  • Framework DecodingUtils.framework -> DU
    • Class ComplexFileDecoder in framework -> DUComplexFileDecoder
      • Private Prefix -> DUCFD
        • Private Method close -> - (void)DUCFD_close
        • 私有方法关闭 - > - (void)DUCFD_close
      • 私有前缀 - > DUCFD私有方法关闭 - > - (void)DUCFD_close
    • 框架中的类ComplexFileDecoder - > DUComplexFileDecoder私有前缀 - > DUCFD私有方法关闭 - > - (void)DUCFD_close
  • 框架DecodingUtils.framework - >框架中的DU类ComplexFileDecoder - > DUComplexFileDecoder私有前缀 - > DUCFD私有方法关闭 - > - (void)DUCFD_close

Alternatively append the prefix at the end of the fist method argument name, to get better auto-completion:

或者在第一个方法参数名称的末尾附加前缀,以获得更好的自动完成:

- (void)doSomethingWith:(Type1)var1 parameters:(Type2)var2

will become

会变成

- (void)doSomethingWith_DUCFD:(Type1)var1 parameters:(Type2)var2

or always only append it to the last parameter name:

或者始终只将它附加到最后一个参数名称:

- (void)doSomethingWith:(Type1)var1 parameters_DUCFD:(Type2)var2

or (now it gets really crazy) - add a fake dummy parameter just for naming:

或者(现在它真的很疯狂) - 添加一个假的伪参数只是为了命名:

- (void)doSomethingWith:(Type1)var1 parameters:(Type2)var2 DUCFD:(id)x

where x is actually never used in the method and you pass nil for it:

其中x实际上从未在方法中使用过,你为它传递了nil:

[self doSomethingWith:var1 parameters:var2 DUCFD:nil];

and as it will always be the same at the end, use a pre-processor macro:

并且因为它在最后总是相同,所以使用预处理器宏:

#define priv DUCFD:nil
#define PRIVATE DUCFD:nil

// ...

[self doSomethingWith:var1 parameters:var2 priv];
[self doSomethingWith:var1 parameters:var2 PRIVATE];

Prefix and suffixing works also with properties (and thus their ivar, getter/setter methods), the preproessor trick above won't, of course.

前缀和后缀也适用于属性(因此它们的ivar,getter / setter方法),当然前面的前导技巧也不会。

#7


0  

Regarding Apple recommendations. You might be interested in how Apple writes it's own code.

关于Apple的建议。您可能对Apple如何编写自己的代码感兴趣。

If you check private APIs you will see that they use underscores for private methods everywhere. Every peace of Obj-C code in iOS uses them. And in many cases those methods go through multiple iOS versions without refactoring or renaming which means it's not a temporary solution for them but rather a convention. In fact, there're three levels of private methods they use extensively - no underscore, single and double underscore.

如果您检查私有API,您会看到他们在任何地方都使用下划线作为私有方法。 iOS中每个Obj-C代码的和平使用它们。在许多情况下,这些方法经过多个iOS版本而无需重构或重命名,这意味着它不是一个临时解决方案,而是一个约定。实际上,他们广泛使用的是三种级别的私有方法 - 没有下划线,单下和双下划线。

As for other solutions like "private", class or project name prefixes - they don't use them at all. Just underscores.

至于其他解决方案,如“私人”,类或项目名称前缀 - 他们根本不使用它们。只是强调。