memisahkan deklarasi dari definisi

Saya benar-benar ingin menggunakan D karena konstruksi bahasanya begitu melakukan banyak hal yang saya pedulikan lebih baik daripada C++, tetapi GC yang hampir dipaksakan (masalah ditangani [semacam] di sini), kelebihan beban operator yang sedikit kurang kuat (kecuali opDispatch.opDispatch seksi), dan masalah berikut agak membuat saya kesal.

Apakah mungkin di D untuk memisahkan deklarasi metode dari definisi? Jika ya, bagaimana caranya? Jika tidak, mengapa?

Contoh motivasi untuk 'bagaimana': untuk menyediakan file header kecil dari fungsi antarmuka di sebelah objek biner, seperti header dan pustaka C, demi menyembunyikan implementasi dari pandangan penulis kode pengguna. Preferensi: tanpa bergantung pada apakah kode pengguna telah meretas pengumpul sampah atau hanya mengkompilasi tanpa waktu mabuk (seperti ini ditemukan di komentar di sini).


d
person user    schedule 05.08.2013    source sumber
comment
Baca tentang file antarmuka D.   -  person DejanLekic    schedule 06.08.2013
comment
@DejanLekic Saya hanya melihat file antarmuka D yang ditentukan di bagian dokumentasi pada kompiler. Apakah ini masalah kompiler demi kompiler atau masalah bahasa? EDIT: Blargh, baca lebih jauh tentangnya. Itu bukan bagian dari bahasa tersebut. Apakah ada solusi yang ADALAH bagian dari bahasa tersebut?   -  person user    schedule 06.08.2013
comment
File antarmuka D hanya menggunakan bagian berbeda dari bahasa D yang sama. (Faktanya, kompiler dmd tidak peduli apakah ekstensinya .d atau .di, semuanya bekerja dengan cara yang sama.)   -  person Adam D. Ruppe    schedule 06.08.2013
comment
@AdamD.Ruppe Baik - tetapi bisakah Anda memperjelas kutipan berikut (dari dlang.org/ dmd-linux.html#interface_files): File antarmuka D memiliki beberapa kesamaan analog dengan file header C++. Tapi mereka tidak diperlukan seperti file header C++, dan mereka bukan bagian dari bahasa D. Mereka adalah fitur kompiler, dan hanya berfungsi sebagai optimalisasi proses pembangunan.   -  person user    schedule 06.08.2013
comment
@ AdamD.Ruppe Maksud saya, untuk lebih jelasnya, saya tidak akan menjadi seorang yang murni dan mengatakan bahwa file .di yang tidak menjadi bagian dari definisi bahasa inti adalah suatu hal yang tidak menguntungkan. Aku hanya ingin tahu ada apa dengan mereka.   -  person user    schedule 06.08.2013


Jawaban (3)


Jika saya menulis file D seperti ini: http://arsdnet.net/dcode/iface/test.d dan Anda mengkompilasi dengan dmd -c, Anda akan melihatnya berjalan tanpa kesalahan; itu file D yang valid. Bahasa ini memungkinkan Anda menulis prototipe fungsi tanpa implementasi.

File .di memang seperti itu, hanya saja nama filenya berbeda.

Kemudian diberikan main: http://arsdnet.net/dcode/main.d jika Anda mengkompilasi dmd utama, ia akan secara otomatis mencari iface/test.d ketika ia melihat "import iface.test;", temukan file .d itu, atau .di jika Anda mengganti namanya tetapi tetap sama, dan dapatkan definisi antarmuka Anda.

dmd main akan gagal dengan kesalahan linker, jadi kita perlu mengimplementasikannya: http://arsdnet.net/dcode/impl.d Catatan: impl TIDAK mengimpor modul, sehingga tidak pernah memeriksa file lainnya. Menjaga file .di dan .d tetap sinkron adalah salah satu bagian rumit di sini, kecuali Anda membuat file antarmuka secara otomatis, karena metode yang tidak ditentukan akan menghasilkan kesalahan linker, namun urutan metode penting: harus cocok, dan begitu juga daftar variabel jika ada variabel publik. Jika tidak, kode penggunaan dan kode implementasi tidak akan sesuai dengan tata letak kelas.

Sekali lagi, ia tidak memeriksa bahwa secara otomatis, file implementasi tidak melihat file "header" sama sekali, jadi ini adalah perbedaan besar dari C++ di mana Anda menulis file header satu kali, lalu gunakan itu di program penggunaan dan file implementasi.

Anda akan melihat bahwa file implementasi juga mencantumkan kelas, dll. D tidak mendukung sintaks void MyClass::add(int a) {} C++ harus menulis metode di luar kelas.

Sejauh yang saya tahu, tidak ada cara untuk memaksa file implementasi untuk mencari header, jika Anda meletakkan keduanya di baris perintah, Anda mendapatkan: "Kesalahan: modul iface.test dari file iface/test.d bertentangan dengan modul lain tes dari file impl.d"

Cara penggunaan file .di yang direkomendasikan adalah dengan membuatnya secara otomatis dengan dmd -H. Ini membaca file implementasi penuh dan menghapus isi fungsi, hanya menyisakan definisi. Bagian ini mungkin adalah kuncinya ketika mereka mengatakan ini adalah fitur kompiler - file .di valid dan standar D, tetapi dihasilkan melalui opsi kompiler yang tidak harus menjadi bagian dari kompiler lain.

person Adam D. Ruppe    schedule 06.08.2013
comment
dmd main untuk melihat kesalahan dan dmd main.d impl.d untuk melihatnya berjalan dengan sukses. Unduh kedua file ke folder Anda sendiri. - person Adam D. Ruppe; 24.06.2015

Anda dapat mendeklarasikan fungsi tanpa menentukan implementasinya dengan menggunakan extern, misalnya:

extern(D):
void foo(string name);

Kemudian cukup sediakan file/arsip objek dengan implementasi untuk penautan. Perhatikan bahwa nama modul adalah bagian dari nama fungsi yang rusak sehingga file header memerlukan nama modul yang sama dengan modul yang dikompilasi atau Anda dapat menggunakan extern(C) untuk menonaktifkan kerusakan (mencegah kelebihan beban dan menggunakan konvensi panggilan C).

person Justin W    schedule 05.08.2013
comment
FWIW, file .di hanyalah otomatisasi dari konvensi itu. - person BCS; 06.08.2013
comment
@BCS Dan dengan demikian semuanya menjadi pelajaran bagi saya. Terima kasih semuanya. - person user; 07.08.2013

Adam sudah menjelaskan semuanya. Saya hanya akan mencoba menambahkan contoh tambahan:

Katakanlah Anda sedang mengembangkan perpustakaan bernama mylib dan memiliki fungsi foo() dan bar(). Aplikasi pengujian kode dan pustaka Anda mungkin terlihat seperti ini di awal:

mylib.d - file antarmuka

module mylib;

void foo();
void bar();

mylib_impl.d - definisi ada di sini

module mylib;

import std.stdio;

void foo() {
  writeln("foo()");
}

void bar() {
  writeln("bar()");
}

mylib_test.d - aplikasi pengujian

// To compile: dmd mylib_impl.d mylib_test.d
// NOTE: we do not compile the "interface" file mylib.d !!
module mylib_test;

import mylib;

int main() {
  foo();
  bar();

  return 0;
}

Sekarang seharusnya tidak sulit untuk memahami bahwa kita memiliki file .di semata-mata untuk kenyamanan dan kejelasan. Jika kami memutuskan untuk menggunakan file antarmuka, kami akan mengganti nama mylib.d menjadi mylib.di, dan mylib_impl.d menjadi mylib.d. mylib_test.d akan tetap utuh.

person DejanLekic    schedule 06.08.2013
comment
Paket hanyalah sebuah direktori. Ini harus berfungsi tanpa perubahan. - person DejanLekic; 24.06.2015