Bölümlendirilmiş Üstbilgiler

J2ObjC tarafından oluşturulan üstbilgi dosyaları segmentlere ayrılır ve tek seferde bir segment eklenebilir. Çevrilmiş her Java türü için bir segment oluşturulur. Böylece her iç sınıfın kendi segmenti olur. Ön işlemci makroları, derleyiciye yalnızca başlığı dahil ederken belirli bir segmenti okumasını söylemek için kullanılır. Segmentlere ayrılmış başlıklar, J2ObjC tarafından oluşturulan başlıklarda döngüleri dahil etme sorununu çözer. Bu sorun aşağıda ayrıntılı olarak açıklanmıştır.

Bilmeniz gerekenler

  • J2ObjC tarafından oluşturulan üstbilgileri eklemek için #import yerine #include kullanın.
    • #import'ın segmentlere ayrılmış başlıklarla kullanılması sorunludur. Çünkü derleyici, başlığı zaten görmüşse okumayı atlar. Ancak, başlık segmentlere ayrıldığından ilk kez derleyici tarafından tam olarak ayrıştırılmamış olabilir.
  • Segmentlere ayrılmış başlıklar, --no-segmented-headers işaretiyle devre dışı bırakılabilir.

Dairesel İçerikler

J2ObjC tarafından oluşturulan üstbilgi dosyaları, gerekli tür bilgilerini çözümlemek için dahil etme ve yönlendirme bildirimleri kullanmalıdır. Yönlendirilen bildirimler mümkün olduğunca çok kullanılır ancak derleyici tam tür bildirimini gerektirdiğinden genişletilen veya uygulanan türler için şunları içerir:

J2ObjC tarafından oluşturulan üstbilgi dosyalarında dahil etme döngüleri oluşturulabilir. Böyle bir döngü elde etmek için A dosyasında B dosyasındaki bir sınıfı genişleten bir sınıf, B dosyasında A dosyasındaki bir sınıfı genişleten bir sınıf olması gerekir. Bu, pek olası olmayan bir senaryo olsa da Guava'nın kod tabanında (ve başka yerlerde) yaşanıyor.

Bu sorunun doğal bir çözümü, .java dosyasında karşılaşılan her Java türü için ayrı bir üstbilgi dosyası yayınlamak olabilir. Ancak J2ObjC, derleme aracı olarak kullanılmak üzere tasarlanmıştır ve tüm iyi derleme sistemleri, her giriş için tahmin edilebilir çıkışlara ihtiyaç duyar. Bu, her bir .java dosyasının tam olarak bir .h ve bir .m dosyası oluşturması gerektiği anlamına gelir.

Örnek

Foo.java:

class Foo extends Bar {}

Bar.java:

class Bar {
  static class Baz extends Foo {}
}

Foo.h (segmentlere ayrılmamış):

#ifndef _Foo_H_
#define _Foo_H_

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

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

#endif // _Foo_H_

Bar.h (segmentlere ayrılmamış):

#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'nin Bar.h ve Bar.h içerdiği Foo.h içerdiğine dikkat edin. Sonuç olarak bu üstbilgiler derlenemiyor:

../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
~~~~~~~~~~~~~~   ^

Aşağıda, hata olmadan derlenecek Foo.h ve Bar.h'nin segmentlere ayrılmış sürümleri bulunmaktadır.

Foo.h (segmentli):

#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 (segmentli):

#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")