在没有 getter 和 setter 的 .h 中放置一个实例变量有什么用(即没有人可以设置或获取它)?

What is the use of placing an instance variable in .h where it wouldn't have a getter and setter ( i.e. nobody can set nor get it)?

我已经阅读了Where to put iVars in "modern" Objective-C?和其他一些问题,但我仍然感到困惑。

我正在阅读 https://www.raywenderlich.com/913/sqlite-tutorial-for-ios-making-our-app SQLite 教程:

.h

#import <Foundation/Foundation.h>
#import <sqlite3.h>

@interface FailedBankDatabase : NSObject {
sqlite3 *_database; 
}

+ (FailedBankDatabase*)database;
- (NSArray *)failedBankInfos;

@end

.m

#import "FailedBankDatabase.h"
#import "FailedBankInfo.h"

@implementation FailedBankDatabase

static FailedBankDatabase *_database;

+ (FailedBankDatabase*)database {
    if (_database == nil) {
        _database = [[FailedBankDatabase alloc] init];
    }
    return _database;
}

不对的地方请指正: sqlite3 * database:

所有的意思是我们不能访问也不能设置它! 我们为什么要这样做?

将它放在 .h 文件中的目的是什么;为什么不只是 写成属性还是单独写入我们的.m文件?

编辑: 在 Objective-C 中使用 Sqlite3 的现代方法是什么?

你说得对,sqlite3 *_database 不是 属性,没有合成的 setter 或 getter,但你可以访问它 - 通过直接引用.如果它在 header 中,它是公开声明的,因此任何拥有 FailedBankDatabase 实例的人都可以直接访问 _database 的内存位置并与之交互。它只是不调用 getter 来做。

因为这样使用属性更好。通过要求客户通过 getter 您可以更好地控制访问。

这个static FailedBankDatabase *_database;是同名但完全不相关的变量。它是静态的,因此它具有 class 范围,并且正在访问 _database 的方法的范围决定了正在访问哪个变量。这是令人困惑和糟糕的形式...

并非总是可以在 implementation 块中声明实例变量。这已经有好几年了,但该教程的日期是 2010 年 4 月 8 日。编写它时,作者可能希望它在旧版本的编译器上工作。

因为_database没有声明@private,实际上可以在FailedBankDatabase实现之外访问实例变量。在 Objective-C 中,您可以将对象指针视为结构指针,并像访问结构字段一样访问其实例变量。所以你可以这样做:

#import "FailedBankDatabase.h"

int main(int argc, char *argv[])
{
    FailedBankDatabase *db = [FailedBankDatabase database];
    printf("instance variable: %p\n", db->_database);
    return 0;
}

不过这可能不是个好主意。

更新

由于您的 sqlite3 *_database 是私有的,您可能只想这样做:

FailedBankDatabase.h

#import <Foundation/Foundation.h>

@class FailedBankInfo;

@interface FailedBankDatabase : NSObject

+ (FailedBankDatabase*)database;
- (NSArray<FailedBankInfo *> *)failedBankInfos;

@end

FailedBankDatabase.m

#import "FailedBankDatabase.h"
#import "FailedBankInfo.h"
#import <sqlite3.h>

@implementation FailedBankDatabase {
    sqlite3 *_database;
}

static FailedBankDatabase *theInstance;

+ (FailedBankDatabase*)database {
    if (theInstance == nil) {
        theInstance = [[FailedBankDatabase alloc] init];
    }
    return theInstance;
}