正确的 Objective-C 助手“Wannabe”私有方法?

发布于 2024-11-28 05:41:54 字数 883 浏览 3 评论 0原文

虽然我讨厌在这个问题上把马打死(我已经阅读了有关此问题的各种文章),但只是想在创建我的“自己的约定”以从现在开始编码时使用之前获得更多关于此事的意见在 Objective-C 中。

我想弄清楚的约定最终是如何(使用生产级代码的最佳编码实践)在类中使用私有方法。来自 C# 的背景,当我编写类时,通常有一个代码块在多个公共方法中重复(例如错误检查或 WCF 服务连接设置)。我通常创建此代码的一个块,并将其放入私有方法中,仅供这些公共方法访问。这样,如果我需要进行更改,我只需要在一个位置进行更改,而不是在一个类中的 10 个不同位置进行更改,但永远不会让用户能够调用此私有方法。例如:

public Class A
{
    public void method1()
    {
        doErrorChecking()
        // Do more stuff
    }
    public void method2()
    {
        doErrorChecking()
        // Do more stuff
    }     
    private doErrorChecking() { //Error Checking Code}
}

我知道没有真正的方法可以在 Objective-C 中真正将最后一个方法设为私有,但只是想确保当我在 Objective-C 中为 iOS 开发创建所有未来的类时,我遵循最好的方法可以进行实践,因此将来不需要(希望如此)就此事进行代码重构。我注意到人们谈论类别,其他人只是不将方法放在@interface 文件中,还有人使用扩展方法。目前我只是将方法实现放入@implementation 文件中,而不是接口文件中。我还让“想要的”私有方法有一个真正独特的名称,这样子类化或覆盖方法就不是问题了。这是我应该走的路吗?或者对于这些特定的场景有没有更好的方法来做到这一点?

While I hate to beat a horse to death on this subject (I've read through various articles about this), but would just like to get more opinions on this matter before I create my "own convention" to use from now on while coding in Objective-C.

The convention that I want to figure out is ultimately how to (using best coding practices for production level code) use private methods in a class. Coming from a background in C#, when I write classes, usually there is a block of code that is repeated in multiple public methods (such as error checking, or WCF service connection setup). I usually create one block of this code and put it in a private method for only these public methods to access. This way if I need to make a change, I only need to do it in one spot, as opposed to 10 different places in a class, but then never giving users the ability to call this private method. For example:

public Class A
{
    public void method1()
    {
        doErrorChecking()
        // Do more stuff
    }
    public void method2()
    {
        doErrorChecking()
        // Do more stuff
    }     
    private doErrorChecking() { //Error Checking Code}
}

I understand that there is no real way to truly make that last method private in Objective-C, but just really want to make sure that when I create all future classes in Objective-C for iOS development I'm following the best practice available so future code refactoring on this matter won't be needed (hopefully). I've noticed people talking about categories, others just don't put the method in the @interface file, and others use extension methods. At the moment I'm just putting the method implementation in the @implementation file, but not the interface file. I'm also making the "wannabe" private method have a really distinct name so that sub-classing or overwriting methods is not an issue. Is this the path I should be following? Or for these particular scenarios is there a better way to do it?

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

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

发布评论

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

评论(3

甜心小果奶 2024-12-05 05:41:54

是的,想要将功能提取到另一种方法中是完全合理的。在我看来,最好的方法是使用类延续,您可以将私有方法声明放入其中。它可以位于 @implementation 块之上code>.m 文件,因此它不在公共标头中。

@interface MyClass ()
- (void)_privateMethod:(id)arg;
@end

类延续和普通类别(例如@interface MyClass (PrivateMethods))之间的区别在于,编译器将要求您实现主@implementation中的方法块,而不是有一个单独的 @implementation MyClass (PrivateMethods) 块。在实现您所描述的辅助方法时,这可以说是可取的。

在命名方面,_ 开头的私有方法名称(以及 ivar 名称)相对常见,尽管不是每个人都这样做— 显然 Apple 为自己保留此,因此您应该选择不同的前缀。该语言不强制执行任何内容。

Yes, it's perfectly reasonable to want to extract your functionality out into another method. The best way to do this in my opinion is using a class continuation, which you can put your private method declarations in. It can go above your @implementation block in your .m file, so it's not in the public header.

@interface MyClass ()
- (void)_privateMethod:(id)arg;
@end

The difference between a class continuation and a normal category (such as @interface MyClass (PrivateMethods)) is that the compiler will require you to implement the methods in your main @implementation block, rather than having a separate @implementation MyClass (PrivateMethods) block. This is arguably desirable when implementing helper methods like you described.

In terms of naming, it's relatively common to start private method names (and ivar names, for that matter) with an _, though not everyone does — apparently Apple reserves this for themselves, so you should pick a different prefix. The language doesn't enforce anything.

对你而言 2024-12-05 05:41:54

我肯定会使用类扩展。在实现文件中,在 @implementation 上方包含类似的内容:

@interface A ()
- (void) doErrorChecking;
@end

然后根据需要在代码中使用该方法。尽管由于 Objective-C 的动态特性,没有任何方法是真正私有的,但这会掩盖接口文件中的方法,同时在技术上仍将其包含在您自己的“私有”接口中。一般来说,保留适合公共使用的方法和属性的 .h 文件,同时将私有使用的方法和属性限制为实现文件中的类扩展。

I would use a class extension, definitely. In the implementation file, include something like this above your @implementation:

@interface A ()
- (void) doErrorChecking;
@end

Then use the method in code as needed. Although due to objective-c's dynamic nature no method is truly private, this will obscure the method from your interface file while still technically including it in your own 'private' interface. In general, keep your .h file for methods and properties that are ok for public use, while limiting private use methods and properties to a class extension in the implementation file.

离旧人 2024-12-05 05:41:54

如果您只需要一组绝对不能被子类覆盖的可​​重用代码,您可以创建一个常规 C 函数而不是方法。如果该函数是在类@implementation块的范围内声明的,它仍然可以访问该对象的所有私有ivars。不过,您需要传递一个指向 self 的指针,因为函数没有绑定到特定对象

所以它看起来像这样:

static BOOL isInValidState(MyClass *);

@implementation MyClass

static BOOL isInValidState(MyClass *self) {
    if (self->somePrivateIvar == nil) {
        return NO;
    }

    if ([self->someString isEqualToString:@"pigsAreFlying"]) {
        return NO;
    }

    return YES;
}

- (void)method1 {
    if (isInValidState(self) == NO) {
        return;
    }
    // Do whatever method 1 does
}

- (void)method2 {
    if (isInValidState(self) == NO) {
        return;
    }
    // Do whatever method 2 does
}

@end

因为函数不是方法列表的一部分类,此错误检查方法永远不能被覆盖。由于我们将其声明为static,因此只能在此文件的范围内访问它,这意味着它实际上是私有的;它不能被任何其他类的对象调用。

If you just need a reusable set of code that absolutely cannot be overridden by a subclass, you could just make a regular C function instead of a method. If the function is declared within the scope of the class @implementation block, it can still get access to all the private ivars of the object. You'd need to pass in a pointer to self, though, since a function isn't bound to a particular object

So it would look like this:

static BOOL isInValidState(MyClass *);

@implementation MyClass

static BOOL isInValidState(MyClass *self) {
    if (self->somePrivateIvar == nil) {
        return NO;
    }

    if ([self->someString isEqualToString:@"pigsAreFlying"]) {
        return NO;
    }

    return YES;
}

- (void)method1 {
    if (isInValidState(self) == NO) {
        return;
    }
    // Do whatever method 1 does
}

- (void)method2 {
    if (isInValidState(self) == NO) {
        return;
    }
    // Do whatever method 2 does
}

@end

Since functions are not part of the method list of a class, this error checking method cannot ever be overridden. Since we declared it static, it is only accessible within the scope of this file, which means that it's effectively private; it cannot be called by an object of any other class.

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