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)?

試著忘記壹切 提交于 2019-12-21 20:56:41

问题


I have read Where to put iVars in "modern" Objective-C? and some other questions, but I am still confused.

I am reading from https://www.raywenderlich.com/913/sqlite-tutorial-for-ios-making-our-app SQLite Tutorial:

.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;
}

Please correct where I am wrong: The sqlite3 * database:

  • Isn't a property
  • Doesn't have any synthesize
  • Doesn't have any setter or getter in .m file so no other class can access it--defeating the purpose of placing in .h file

All meaning we can't access nor set it! Why are we doing this?

What what is the purpose of placing this in .h file; Why not just write as a property? Or just write in our .m file alone?

Edit: What is the modern way of using Sqlite3 in Objective-C?


回答1:


It was not always possible to declare instance variables in the implementation block. It has been possible for several years, but the date of that tutorial is April 8, 2010. When it was written, the author probably wanted it to work on older versions of the compiler.

Because _database is not declared @private, it is in fact possible to access the instance variable outside of the FailedBankDatabase implementation. In Objective-C, you can treat an object pointer as a struct pointer and access its instance variables like struct fields. So you could do this:

#import "FailedBankDatabase.h"

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

That's probably a bad idea, though.

UPDATE

Since your sqlite3 *_database is intended to be private, you probably just want to do this:

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;
}



回答2:


You're part right, sqlite3 *_database isn't a property, has no synthesised setter or getter, but you can access it - by direct reference. If it's in the header it's publicly declared so anyone with an instance of FailedBankDatabase can directly access the memory location of _database and interact with it. It just doesn't call a getter to do it.

Because of this using properties is better. By asking clients to go through the getter you have more control over access.

This static FailedBankDatabase *_database; is a same name but completely unrelated variable. It's static so it has class scope and the scope of the method which is accessing _database determines which variable is being accessed. This is confusing and bad form...



来源:https://stackoverflow.com/questions/36576705/what-is-the-use-of-placing-an-instance-variable-in-h-where-it-wouldnt-have-a-g

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!