在没有 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
:
- 不是 属性
- 没有任何合成
- .m 文件中没有任何 setter 或 getter,因此没有其他 class 可以访问它——破坏了放置在
.h
文件中的目的
所有的意思是我们不能访问也不能设置它! 我们为什么要这样做?
将它放在 .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;
}
我已经阅读了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
:
- 不是 属性
- 没有任何合成
- .m 文件中没有任何 setter 或 getter,因此没有其他 class 可以访问它——破坏了放置在
.h
文件中的目的
所有的意思是我们不能访问也不能设置它! 我们为什么要这样做?
将它放在 .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;
}