ไฟล์ส่วนหัวที่สร้างด้วย J2ObjC จะแบ่งออกเป็นกลุ่มๆ และสามารถมีได้ทีละ 1 กลุ่ม โดยมีเซกเมนต์ 1 ส่วนสำหรับ Java แต่ละประเภทที่แปลไว้ ดังนั้นคลาสภายในแต่ละคลาสจะมีเซกเมนต์ของตัวเอง มาโครตัวประมวลผลล่วงหน้าใช้เพื่อบอกให้คอมไพเลอร์อ่านเฉพาะบางส่วนเมื่อใส่ส่วนหัวเท่านั้น ส่วนหัวที่มีการแบ่งส่วนจะช่วยแก้ปัญหารอบการรวมในส่วนหัวที่สร้างโดย J2ObjC ซึ่งอธิบายรายละเอียดไว้ด้านล่าง
สิ่งที่จำเป็นต้องทราบ
- ใช้
#include
แทน#import
เพื่อรวมส่วนหัวที่ J2ObjC สร้างขึ้น- การใช้
#import
กับส่วนหัวที่แบ่งเป็นส่วนๆ จะทำให้เกิดปัญหาเพราะคอมไพเลอร์จะข้ามการอ่านส่วนหัวนั้นหากเคยเห็นแล้ว แต่เนื่องจากส่วนหัวมีการแบ่งกลุ่ม จึงอาจไม่ได้รับการแยกวิเคราะห์ทั้งหมดโดยคอมไพเลอร์ในครั้งแรก
- การใช้
- ปิดใช้ส่วนหัวที่แบ่งกลุ่มได้ด้วยแฟล็ก
--no-segmented-headers
หนังสือเวียน
ไฟล์ส่วนหัวที่สร้างโดย J2ObjC ต้องใช้การประกาศรวมและส่งต่อเพื่อแก้ไขข้อมูลประเภทที่จำเป็น ระบบจะใช้การประกาศล่วงหน้าให้มากที่สุด แต่จะมีการรวมประเภทที่มีความจำเป็นสําหรับประเภทที่กำลังขยายหรือใช้งาน เนื่องจากคอมไพเลอร์จำเป็นต้องมีการประกาศประเภทที่สมบูรณ์
คุณสามารถสร้างรอบการรวมในไฟล์ส่วนหัวที่ J2ObjC สร้างขึ้นได้ ในการสร้างวงจรนี้ เราต้องใช้คลาสในไฟล์ A ที่ขยายคลาสในไฟล์ B และคลาสในไฟล์ B ที่ขยายคลาสในไฟล์ A กรณีนี้ไม่เกิดขึ้นบ่อยนัก แต่เกิดขึ้นในฐานของโค้ดของ Guava (และที่อื่นๆ)
วิธีแก้ไขโดยทั่วไปสำหรับปัญหานี้คือการปล่อยไฟล์ส่วนหัวแยกต่างหากสำหรับ Java แต่ละประเภทที่พบในไฟล์ .java แต่ J2ObjC ออกแบบมาให้ใช้เป็นเครื่องมือบิลด์ และระบบบิลด์ที่ดีจะอาศัยเอาต์พุตที่คาดการณ์ได้สำหรับอินพุตแต่ละรายการ ซึ่งหมายความว่าไฟล์ .java แต่ละไฟล์จะต้องสร้างไฟล์ .h และ .m ได้ 1 ไฟล์
ตัวอย่าง
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 จะมี Foo.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")