ส่วนหัวที่แบ่งกลุ่ม

ไฟล์ส่วนหัวที่ J2ObjC สร้างขึ้นจะแบ่งออกเป็นกลุ่มๆ และสามารถรวมได้ทีละกลุ่ม ระบบจะสร้างกลุ่ม 1 กลุ่มสําหรับประเภท Java ที่แปลแล้วแต่ละประเภท ดังนั้นคลาสย่อยแต่ละคลาสจะมีกลุ่มของตัวเอง มาโครของโปรแกรมประมวลผลข้อมูลล่วงหน้าใช้เพื่อบอกคอมไพเลอร์ให้อ่านเฉพาะส่วนที่ต้องการเมื่อรวมส่วนหัว ส่วนหัวแบบแบ่งกลุ่มช่วยแก้ปัญหาวงจรรวมในส่วนหัวที่ J2ObjC สร้างขึ้น ซึ่งอธิบายไว้อย่างละเอียดในเอกสารนี้

สิ่งที่คุณจำเป็นต้องทราบ

  • ใช้ #include แทน #import เพื่อรวมส่วนหัวที่ J2ObjC สร้างขึ้น
    • การใช้ #import กับส่วนหัวแบบแบ่งส่วนจะทำให้เกิดปัญหาเนื่องจากคอมไพเลอร์จะข้ามการอ่านส่วนหัวหากเคยเห็นแล้ว แต่เนื่องจากส่วนหัวมีการแบ่งกลุ่ม คอมไพเลอร์จึงอาจไม่ได้แยกวิเคราะห์อย่างสมบูรณ์ในครั้งแรก
  • คุณปิดใช้ส่วนหัวแบบแบ่งกลุ่มได้ด้วย Flag --no-segmented-headers

เนื้อหาในวงกลม

ไฟล์ส่วนหัวที่ J2ObjC สร้างขึ้นต้องใช้การรวมและการประกาศแบบส่งต่อเพื่อแก้ไขข้อมูลประเภทที่จำเป็น ระบบจะใช้การประกาศแบบส่งต่อมากที่สุดเท่าที่จะเป็นไปได้ แต่จำเป็นต้องใช้การรวมสำหรับประเภทที่จะขยายหรือนำไปใช้งาน เนื่องจากคอมไพเลอร์กำหนดให้มีการประกาศประเภทอย่างเต็มรูปแบบ

ระบบอาจสร้างรอบการรวมในไฟล์ส่วนหัวที่ J2ObjC สร้างขึ้น หากต้องการสร้างวงจรดังกล่าว เราต้องมีคลาสในไฟล์ ก ที่ขยายคลาสในไฟล์ ข และคลาสในไฟล์ ข ที่ขยายคลาสในไฟล์ ก สถานการณ์นี้เกิดขึ้นได้น้อย แต่เกิดขึ้นในโค้ดเบสของ Guava (และที่อื่นๆ)

การแก้ปัญหาที่เป็นไปได้คือการสร้างไฟล์ส่วนหัวแยกต่างหากสำหรับประเภท Java แต่ละประเภทที่พบในไฟล์ .java แต่ J2ObjC ออกแบบมาเพื่อใช้เป็นเครื่องมือสร้าง และระบบการสร้างที่ดีจะอาศัยเอาต์พุตที่คาดการณ์ได้สำหรับอินพุตแต่ละรายการ ซึ่งหมายความว่าไฟล์ .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 รวม 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")