सेगमेंट किए गए हेडर

J2ObjC जनरेट की गई हेडर फ़ाइलों को सेगमेंट में बांटा जाता है और उनमें एक बार में एक सेगमेंट शामिल किया जा सकता है. हर अनुवाद किए गए Java टाइप के लिए एक सेगमेंट बनाया जाता है, इसलिए हर इंटरनल क्लास का अपना अलग सेगमेंट होगा. प्रीप्रोसेसर मैक्रो का इस्तेमाल, कंपाइलर को यह बताने के लिए किया जाता है कि हेडर को शामिल करते समय सिर्फ़ कोई खास सेगमेंट पढ़े. सेगमेंट वाले हेडर, J2ObjC जनरेट किए गए हेडर में शामिल साइकल से जुड़ी समस्या का हल करते हैं. इसके बारे में नीचे ज़्यादा जानकारी दी गई है.

आपको क्या जानने की आवश्यकता है

  • J2ObjC जनरेट किए गए हेडर को शामिल करने के लिए, #import के बजाय #include का इस्तेमाल करें.
    • सेगमेंट वाले हेडर के साथ #import का इस्तेमाल करने में समस्या आती है, क्योंकि अगर कंपाइलर ने हेडर को पहले ही देख लिया है, तो वह उसे पढ़ नहीं पाएगा. हालांकि, हेडर को सेगमेंट में बांटने की वजह से, हो सकता है कि कंपाइलर ने पहली बार इसे पूरी तरह से पार्स न किया हो.
  • सेगमेंट किए गए हेडर को --no-segmented-headers फ़्लैग से बंद किया जा सकता है.

सर्कुलर शामिल है

J2ObjC की जनरेट की गई हेडर फ़ाइलों में ज़रूरी जानकारी को शामिल करने और फ़ॉरवर्ड करने से जुड़े एलानों का इस्तेमाल किया जाना चाहिए. फ़ॉरवर्ड की गई जानकारी का इस्तेमाल ज़्यादा से ज़्यादा किया जाता है. हालांकि, टाइप को बढ़ाने या लागू करने के लिए यह ज़रूरी है, क्योंकि कंपाइलर के लिए पूरी तरह की जानकारी देना ज़रूरी होता है.

J2ObjC से जनरेट की गई हेडर फ़ाइलों में, शामिल करने वाले साइकल जनरेट किए जा सकते हैं. ऐसा करने के लिए, हमें फ़ाइल A में एक क्लास चाहिए, जो फ़ाइल B में क्लास को बढ़ाए और फ़ाइल B में ऐसी क्लास को बढ़ाए जो फ़ाइल A की क्लास को बढ़ाए. ऐसा होने की संभावना कम है, लेकिन ऐसा 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")