4

@interfaceで定義せずに、クラスの@implementationでメソッドを作成するにはどうすればよいですか?

たとえば、初期化を行ってからファイルからデータを読み取るコンストラクターがあります。ファイル読み取りコードを別のメソッドに分解して、コンストラクター内から呼び出したいと思います。このメソッドはこの@implementationコンテキストに対してのみプライベートであるため、ヘッダーでこのメソッドを定義したくありません。

これは可能ですか?

これが私の例です。ファイルからTodoタスクリストを読み取る小さなプログラムがあります。

@interfaceは次のとおりです。

@interface TDTaskList : NSObject {
  NSString* name; // The name of this list.
  NSMutableArray* tasks;  // The set of tasks in this list.
}

-(id)initListOfName:(NSString*)aName;
-(NSArray*)loadListWithName:(NSString*)aName;

@end

そしてここに@implementationの一部があります:

-(id)initListOfName:(NSString*)aName {
  if (self = [super init]) {
    name = aName;

    NSArray* aTasks = [self loadListWithName:aName];
    tasks = [NSMutableArray arrayWithArray:aTasks];
  }

  return self;
}

-(NSArray*)loadListWithName:(NSString*)aName {
  // TODO This is a STUB till i figure out how to read/write from a file ...

  TDTask* task1 = [[TDTask alloc] initWithLabel:@"Get the Milk."];
  TDTask* task2 = [[TDTask alloc] initWithLabel:@"Do some homework."];

  return [NSArray arrayWithObjects:task1, task2, nil];
}

私がやりたいのは、インターフェースで以下を定義する必要がないことです。

-(NSArray*)loadListWithName:(NSString*)aName;
4

4 に答える 4

10

メソッドを呼び出すコードの前にメソッドの実装を配置する場合、ヘッダーで定義する必要はありません。

したがって、この場合、 @implementation ブロックの initListOfName: の前に loadListWithName: を配置すると、うまくいきます

注:ヘッダーで定義されていないからといって、オブジェクトの外部のコードからメソッドを呼び出せないわけではありません。Objective-C にはプライベート メソッドがありません。

于 2008-12-30T00:23:11.327 に答える
6

Andy がコメントで示唆したように、拡張機能(名前のないカテゴリのように見えます) を使用できます。違いは、拡張機能で宣言されたメソッドを実装する必要があるのに対し、コンパイラは、カテゴリで宣言されたメソッドの実装を検証しないことです。

.h:

@interface MyObject : NSObject
{
    NSNumber *number;
}
- (NSNumber *)number;
@end

.m:

@interface MyObject ()
- (void)setNumber:(NSNumber *)newNumber;
@end

@implementation MyObject

- (NSNumber *)number
{
    return number;
}
- (void)setNumber:(NSNumber *)newNumber
{
    number = newNumber;
}
@end
于 2008-12-28T10:25:00.397 に答える
2

カテゴリを使用できます:

// In TDTaskList.m
@interface TDTaskList(TDTaskListPrivate)
-(id)initListOfName:(NSString*)aName;
-(NSArray*)loadListWithName:(NSString*)aName;
@end

@implementation TDTaskList(TDTaskListPrivate)

// implementation of initListOfName and loadListWithName ...

@end
于 2008-12-28T01:30:12.303 に答える
1

合理的な選択肢が 2 つあります。どちらも基本的にはすでに説明されていますが、私見は少し不明確であるか、まったく間違っていました.

カテゴリは、実装を複数のソースファイルに分割するというまったく異なる目的を意図しているため、その 1 つではありません。

  • 上記の Nathan のように実行します。彼は最後の仮定(プライベートメソッド)に間違っていますが。
  • プライベート メソッド拡張定義を使用して、次のように前方参照を許可します。

    1. ヘッダーから loadListWithName の定義を完全に削除します
    2. 以下をソース (.m) の @implementation ブロックの前に追加します
    @interface TDTaskList (PrivateMethods)
    -(NSArray*)loadListWithName:(NSString*)aName;
    @終わり
    
    @実装 ...
    

  • 于 2009-04-30T18:31:03.180 に答える