כותרות מפולחות

קובצי כותרות שנוצרו על ידי J2ObjC מחולקים למקטעים וניתן לכלול בהם מקטע אחד בכל פעם. לכל סוג Java נוצר פלח אחד, כך שלכל מחלקה פנימית יהיה קטע נפרד. פקודות מאקרו של מעבד מראש נועדו להורות למידר לקרוא רק קטע מסוים כשהוא כולל את הכותרת.כותרות מפולחות פותרות את הבעיה של הכללת מחזורי הכללה בכותרות שנוצרו על ידי J2ObjC, כפי שמתואר בהמשך.

המידע העיקרי מבחינתך

  • יש להשתמש ב-#include במקום ב-#import כדי לכלול כותרות שנוצרו על ידי J2ObjC.
    • השימוש ב-#import עם כותרות מפולחות הוא בעייתי כי המהדר ידלג על קריאת הכותרת אם הוא כבר ראה אותה. עם זאת, מכיוון שהכותרת מחולקת, ייתכן שהיא לא נותחה במלואה על ידי המהדר בפעם הראשונה.
  • אפשר להשבית כותרות מפולחות עם הדגל --no-segmented-headers.

מעגלי כולל

בקובצי כותרת שנוצרו על ידי J2ObjC חייבים להשתמש בהצהרות הכללה והעברה כדי לטפל בפרטי הסוג הנדרשים. אנחנו משתמשים בהצהרות העברה רבות ככל האפשר, אבל יש צורך בסוגים שמרחיבים או מיושמים, כי המהדר דורש את הצהרת הסוג המלאה.

אפשר ליצור מחזורי הכללה בקובצי כותרת שנוצרו על ידי J2ObjC. כדי ליצור מחזור כזה, אנחנו זקוקים למחלקה בקובץ א' שמרחיבה את המחלקה בקובץ ב', ואת המחלקה בקובץ ב' שמרחיבה את המחלקה בקובץ א'. זהו תרחיש לא סביר, אבל הוא מתרחש ב-codebase של גויאבה (ובמקומות אחרים).

פתרון טבעי לבעיה הזו יכול להיות פלט של קובץ כותרת נפרד לכל סוג Java של קובץ Java. אבל J2ObjC נועד לשמש ככלי build, וכל מערכת build טובה מסתמכת על פלטים צפויים לכל קלט. פירוש הדבר הוא שכל קובץ .java יצור קובץ .h וקובץ .m אחד בדיוק.

דוגמה

Foo.java:

class Foo extends Bar {}

Bar.java:

class Bar {
  static class Baz extends Foo {}
}

Foo.h (לא מפולח):

#ifndef _Foo_H_
#define _Foo_H_

#include "Bar.h"
#include "J2ObjC_header.h"

@interface Foo : Bar
- (instancetype)init;
@end

#endif // _Foo_H_

Bar.h (לא מפולח):

#ifndef _Bar_H_
#define _Bar_H_

#include "Foo.h"
#include "J2ObjC_header.h"

@interface Bar : NSObject
- (instancetype)init;
@end

@interface Bar_Baz : Foo
- (instancetype)init;
@end

#endif // _Bar_H_

שימו לב שהתוויות Foo.h כוללות את Bar.h ו-Bar.h. כתוצאה מכך הכותרות האלה לא עוברות הידור:

../dist/j2objcc -c Foo.m
In file included from Foo.m:6:
In file included from ./Bar.h:9:
./Foo.h:12:18: error: cannot find interface declaration for 'Bar', superclass of 'Foo'
@interface Foo : Bar
~~~~~~~~~~~~~~   ^

בהמשך מוצגות הגרסאות המפולחות של Foo.h ו-Bar.h, שיהדרו ללא שגיאות.

Foo.h (מפולח):

#include "J2ObjC_header.h"

#pragma push_macro("Foo_INCLUDE_ALL")
#if Foo_RESTRICT
#define Foo_INCLUDE_ALL 0
#else
#define Foo_INCLUDE_ALL 1
#endif
#undef Foo_RESTRICT

#if !defined (_Foo_) && (Foo_INCLUDE_ALL || Foo_INCLUDE)
#define _Foo_

#define Bar_RESTRICT 1
#define Bar_INCLUDE 1
#include "Bar.h"

@interface Foo : Bar
- (instancetype)init;
@end

#endif

#pragma pop_macro("Foo_INCLUDE_ALL")

Bar.h (מפולח):

#include "J2ObjC_header.h"

#pragma push_macro("Bar_INCLUDE_ALL")
#if Bar_RESTRICT
#define Bar_INCLUDE_ALL 0
#else
#define Bar_INCLUDE_ALL 1
#endif
#undef Bar_RESTRICT

#if !defined (_Bar_) && (Bar_INCLUDE_ALL || Bar_INCLUDE)
#define _Bar_

@interface Bar : NSObject
- (instancetype)init;
@end

#endif

#if !defined (_Bar_Baz_) && (Bar_INCLUDE_ALL || Bar_Baz_INCLUDE)
#define _Bar_Baz_

#define Foo_RESTRICT 1
#define Foo_INCLUDE 1
#include "Foo.h"

@interface Bar_Baz : Foo
- (instancetype)init;
@end

#endif

#pragma pop_macro("Bar_INCLUDE_ALL")