Saya telah bergulat dengan masalah dalam proyek Java tentang referensi melingkar. Saya mencoba memodelkan situasi dunia nyata di mana benda-benda tersebut saling terkait dan perlu saling mengetahui.
Proyek ini adalah model generik dari bermain permainan papan. Kelas dasar tidak spesifik, tetapi diperluas untuk menangani spesifik catur, backgammon dan permainan lainnya. Saya mengkodekan ini sebagai applet 11 tahun yang lalu dengan setengah lusin game yang berbeda, tetapi masalahnya adalah itu penuh dengan referensi melingkar. Saya menerapkannya saat itu dengan menjejalkan semua kelas yang saling terkait dalam satu file sumber, tapi saya mendapatkan ide bahwa itu bentuk yang buruk di Jawa. Sekarang saya ingin menerapkan hal serupa sebagai aplikasi Android, dan saya ingin melakukan hal-hal dengan benar.
Kelasnya adalah:
RuleBook: objek yang dapat diinterogasi untuk hal-hal seperti tata letak awal Dewan, informasi awal permainan Negara lainnya seperti siapa yang bergerak pertama, Bergerak yang tersedia, apa yang terjadi pada keadaan permainan setelah Pindah yang diusulkan, dan evaluasi dari posisi dewan saat ini atau yang diusulkan.
Papan: representasi sederhana papan permainan, yang dapat diinstruksikan untuk mencerminkan Gerakan.
MoveList: daftar Bergerak. Ini adalah tujuan ganda: pilihan langkah yang tersedia pada titik tertentu, atau daftar langkah yang telah dibuat dalam permainan. Ini dapat dibagi menjadi dua kelas yang hampir identik, tetapi itu tidak relevan dengan pertanyaan yang saya ajukan dan dapat memperumitnya.
Pindah: satu gerakan tunggal. Ini mencakup segala sesuatu tentang gerakan sebagai daftar atom: ambil sepotong dari sini, letakkan di sana, lepaskan potongan yang diambil dari sana.
Status: informasi status lengkap dari game yang sedang berlangsung. Tidak hanya posisi Dewan, tetapi MoveList, dan informasi status lainnya seperti siapa yang akan pindah sekarang. Dalam catur kita akan mencatat apakah raja dan benteng masing-masing pemain telah dipindahkan.
Referensi sirkular ada banyak, misalnya: RuleBook perlu tahu tentang status permainan untuk menentukan gerakan apa yang tersedia pada waktu tertentu, tetapi negara permainan perlu menanyakan RuleBook untuk tata letak awal awal dan untuk efek samping apa yang menyertai gerakan sekali itu dibuat (misalnya siapa yang bergerak selanjutnya).
Saya mencoba mengatur kumpulan kelas baru secara hierarkis, dengan RuleBook di atas karena perlu tahu tentang segalanya. Tetapi ini berakibat harus memindahkan banyak metode ke kelas RuleBook (seperti membuat langkah) menjadikannya monolitik dan tidak terlalu mewakili apa yang seharusnya menjadi RuleBook.
Jadi apa cara yang tepat untuk mengatur ini? Haruskah saya mengubah RuleBook menjadi BigClassThatDoesAlmostEverythingInTheGame untuk menghindari referensi melingkar, mengabaikan upaya untuk memodelkan game dunia nyata secara akurat? Atau haruskah saya tetap dengan kelas yang saling tergantung dan membujuk kompiler untuk mengkompilasinya, mempertahankan model dunia nyata saya? Atau ada beberapa struktur valid yang jelas saya hilang?
Terima kasih atas bantuan yang bisa Anda berikan!
sumber
RuleBook
mengambil misState
sebagai argumen, dan mengembalikan yang validMoveList
, yaitu "di sinilah kita sekarang, apa yang bisa dilakukan selanjutnya?"Jawaban:
Pengumpul sampah Jawa tidak mengandalkan teknik penghitungan referensi. Referensi lingkaran tidak menyebabkan masalah apa pun di Jawa. Waktu yang dihabiskan untuk menghilangkan referensi melingkar yang sempurna di Jawa adalah waktu yang terbuang.
Tidak perlu. Jika Anda hanya mengkompilasi semua file sumber sekaligus (misalnya,
javac *.java
), kompiler akan menyelesaikan semua referensi maju tanpa masalah.Iya nih. Kelas aplikasi diharapkan saling tergantung. Mengkompilasi semua file sumber Java yang termasuk dalam paket yang sama sekaligus bukanlah hack yang cerdik, justru cara Java seharusnya bekerja.
sumber
Memang, dependensi melingkar adalah praktik yang dipertanyakan dari sudut pandang desain, tetapi mereka tidak dilarang, dan dari sudut pandang murni teknis mereka bahkan tidak selalu bermasalah , karena Anda tampaknya menganggapnya sebagai: mereka sangat legal dalam kebanyakan skenario, mereka tak terhindarkan dalam beberapa situasi, dan pada beberapa kesempatan langka mereka bahkan dapat dianggap sebagai hal yang berguna untuk dimiliki.
Sebenarnya, ada beberapa skenario di mana kompiler java akan menolak ketergantungan melingkar. (Catatan: mungkin ada lebih banyak, saya hanya bisa memikirkan yang berikut ini sekarang.)
Dalam warisan: Anda tidak dapat memiliki kelas A memperluas kelas B yang pada gilirannya memperluas kelas A, dan sangat masuk akal bahwa Anda tidak dapat memiliki ini, karena alternatifnya sama sekali tidak masuk akal dari sudut pandang logis.
Di antara kelas-kelas metode-lokal: kelas-kelas yang dideklarasikan dalam suatu metode mungkin tidak saling referensi satu sama lain. Ini mungkin hanyalah batasan dari kompiler java, mungkin karena kemampuan untuk melakukan hal seperti itu tidak cukup berguna untuk membenarkan kerumitan tambahan yang harus masuk ke kompiler untuk mendukungnya. (Kebanyakan programmer java bahkan tidak menyadari fakta bahwa Anda dapat mendeklarasikan kelas dalam suatu metode, apalagi mendeklarasikan beberapa kelas, dan kemudian membuat kelas-kelas ini saling referensi satu sama lain.)
Jadi, penting untuk menyadari dan mengeluarkannya dari jalan bahwa upaya untuk meminimalkan dependensi melingkar adalah pencarian kemurnian desain, bukan pencarian kebenaran teknis.
Sejauh yang saya tahu tidak ada pendekatan reduksionis untuk menghilangkan ketergantungan sirkuler, yang berarti bahwa tidak ada resep yang terdiri dari langkah-langkah sederhana yang telah ditentukan sebelumnya "tanpa-otak" untuk mengambil sebuah sistem dengan referensi melingkar, menerapkannya satu demi satu, dan mengakhiri dengan sistem yang bebas dari referensi melingkar. Anda harus meletakkan pikiran Anda untuk bekerja, dan Anda harus melakukan langkah-langkah refactoring yang tergantung pada sifat desain Anda.
Dalam situasi tertentu yang Anda miliki, menurut saya apa yang Anda butuhkan adalah entitas baru, mungkin disebut "Game" atau "GameLogic", yang mengetahui semua entitas lain, (tanpa ada entitas lain yang mengetahuinya, ) sehingga entitas lain tidak harus saling mengenal.
Misalnya, bagi saya tampaknya tidak masuk akal bahwa entitas RuleBook Anda perlu mengetahui apa pun tentang entitas GameState, karena buku aturan adalah sesuatu yang kami konsultasikan untuk bermain, itu bukan sesuatu yang berperan aktif dalam bermain. Jadi, entitas "Game" baru ini yang perlu berkonsultasi dengan buku peraturan dan status permainan untuk menentukan gerakan apa yang tersedia, dan ini menghilangkan dependensi melingkar.
Sekarang, saya pikir saya bisa menebak apa masalah Anda dengan pendekatan ini: mengkodekan entitas "Game" dengan cara agnostik game akan sangat sulit, jadi Anda kemungkinan besar akan berakhir dengan tidak hanya satu tetapi dua entitas yang perlu memiliki implementasi yang dibuat khusus untuk setiap jenis game yang berbeda: entitas "RuleBook" dan "Game". Yang pada gilirannya mengalahkan tujuan memiliki entitas "RuleBook" di tempat pertama. Yah, yang bisa saya katakan tentang ini adalah bahwa mungkin, mungkin saja, aspirasi awal Anda untuk menulis sebuah sistem yang dapat memainkan berbagai jenis permainan mungkin mulia, tetapi mungkin dikandung dengan buruk. Jika saya berada di posisi Anda, saya akan fokus menggunakan mekanisme umum untuk menampilkan keadaan semua game yang berbeda, dan mekanisme umum untuk menerima input pengguna untuk semua game ini,
sumber
Teori permainan memperlakukan game sebagai daftar gerakan sebelumnya (tipe nilai termasuk siapa yang memainkannya) dan fungsi ValidMoves (priorMoves)
Saya akan mencoba dan mengikuti pola ini untuk bagian non UI dari permainan dan memperlakukan hal-hal seperti pengaturan papan sebagai gerakan.
UI kemudian dapat menjadi hal-hal OO standar dengan satu arah referensi ke logika
Perbarui untuk menyingkat komentar
Pertimbangkan Catur. Permainan catur biasanya dicatat sebagai daftar gerakan. http://en.wikipedia.org/wiki/Portable_Game_Notation
daftar langkah mendefinisikan kondisi lengkap permainan jauh lebih baik daripada gambar papan.
Katakan misalnya kita mulai membuat objek untuk Papan, Potongan, Pindahkan dll dan Metode seperti Piece.GetValidMoves ()
pertama-tama kita melihat kita harus memiliki referensi papan tulis, tapi kemudian kita mempertimbangkan castling. yang hanya dapat Anda lakukan jika Anda belum memindahkan raja atau benteng Anda. Jadi kita perlu bendera Pindah Sudah pada raja dan benteng. Demikian pula pion dapat memindahkan 2 kotak pada langkah pertama mereka.
Kemudian kita melihat bahwa dalam menjalankan langkah raja yang sah tergantung pada keberadaan dan keadaan benteng, sehingga papan perlu memiliki potongan-potongan di atasnya dan referensi potongan-potongan itu. kami masuk ke masalah ref melingkar Anda.
Namun, jika kita mendefinisikan Pindahkan sebagai status permainan dan struktur yang tidak dapat diubah sebagai daftar langkah sebelumnya, kami menemukan masalah ini hilang. Untuk melihat apakah kastil itu valid, kita bisa memeriksa daftar langkah keberadaan kastil dan langkah raja. Untuk melihat apakah pion dapat digunakan secara bersamaan, kita dapat memeriksa untuk melihat apakah pion lain membuat gerakan ganda pada langkah sebelumnya. Tidak diperlukan referensi kecuali Aturan -> Pindahkan
Sekarang catur memiliki papan statis, dan peices selalu diatur dengan cara yang sama. Tetapi katakanlah kita memiliki varian di mana kita mengizinkan pengaturan alternatif. mungkin menghilangkan beberapa bagian sebagai cacat.
Jika kita Tambahkan gerakan pengaturan sebagai gerakan, 'dari kotak ke kotak X' dan menyesuaikan objek Aturan untuk memahami gerakan itu, maka kita masih dapat mewakili permainan sebagai urutan gerakan.
Demikian pula jika dalam permainan Anda papan itu sendiri tidak statis, katakanlah kita dapat menambahkan kotak ke catur atau menghapus kotak dari papan sehingga mereka tidak bisa dipindahkan. Perubahan ini juga dapat direpresentasikan sebagai Moves tanpa mengubah struktur keseluruhan mesin Aturan Anda atau harus merujuk objek BoardSetup yang serupa
sumber
boardLayout
adalah fungsi dari semuapriorMoves
(yaitu jika kita mempertahankannya sebagai status, tidak ada yang akan dikontribusikan selain masing-masingthisMove
). Karenanya saran Ewan pada dasarnya adalah "memotong perantara" - bergerak yang sah fungsi langsung dari semua sebelumnya, bukanvalidMoves( boardLayout( priorMoves ) )
.Cara standar untuk menghapus referensi melingkar antara dua kelas dalam pemrograman berorientasi objek adalah dengan memperkenalkan antarmuka yang kemudian dapat diimplementasikan oleh salah satu dari mereka. Jadi dalam kasus Anda, Anda bisa
RuleBook
merujukState
yang kemudian merujuk keInitialPositionProvider
(yang akan menjadi antarmuka yang diimplementasikan olehRuleBook
). Ini juga membuat pengujian lebih mudah, karena Anda kemudian dapat membuatState
yang menggunakan posisi awal yang berbeda (mungkin lebih sederhana) untuk tujuan pengujian.sumber
Saya percaya referensi melingkar dan objek dewa dalam kasus Anda dapat dengan mudah dihapus dengan memisahkan kontrol aliran game dari negara dan model aturan permainan. Dengan melakukan itu Anda mungkin akan mendapatkan banyak fleksibilitas dan menyingkirkan beberapa kompleksitas yang tidak perlu.
Saya pikir Anda harus memiliki controller ("master game" jika Anda mau) yang mengontrol aliran game dan menangani perubahan status aktual alih-alih memberikan buku aturan atau game menyatakan tanggung jawab ini.
Objek status permainan tidak perlu mengubah dirinya sendiri atau menyadari aturan. Kelas hanya perlu menyediakan model yang mudah ditangani (dibuat, diperiksa, diubah, bertahan, dicatat, disalin, dll) dan objek keadaan permainan yang efisien untuk sisa aplikasi.
Buku peraturan seharusnya tidak perlu tahu tentang atau bermain-main dengan game yang sedang berlangsung. Seharusnya hanya memerlukan pandangan ke kondisi permainan untuk dapat mengetahui gerakan mana yang legal dan hanya perlu menjawab dengan keadaan permainan yang dihasilkan ketika ditanya apa yang terjadi ketika suatu langkah diterapkan pada kondisi permainan. Itu juga bisa memberikan keadaan awal permainan ketika ditanya tata letak awal.
Pengontrol harus mengetahui status permainan dan buku peraturan dan mungkin beberapa objek lain dari model permainan, tetapi tidak perlu mengacaukan detailnya.
sumber
Saya pikir masalahnya di sini adalah Anda belum memberikan deskripsi yang jelas tentang tugas apa yang harus ditangani oleh kelas mana. Saya akan menjelaskan apa yang saya pikir merupakan deskripsi yang baik tentang apa yang harus dilakukan oleh setiap kelas, kemudian saya akan memberikan contoh kode generik yang menggambarkan ide-ide tersebut. Kita akan melihat bahwa kodenya kurang digabungkan, sehingga tidak benar-benar memiliki referensi melingkar.
Mari kita mulai dengan menggambarkan apa yang dilakukan setiap kelas.
The
GameState
kelas saja harus berisi informasi tentang keadaan saat permainan. Seharusnya tidak mengandung informasi apa pun tentang kondisi permainan di masa lalu atau pergerakan di masa depan yang mungkin terjadi. Seharusnya hanya berisi informasi tentang potongan apa yang ada di kotak apa dalam catur, atau berapa banyak dan jenis catur apa pada poin apa di backgammon. TheGameState
harus mengandung beberapa informasi tambahan, seperti informasi tentang Castling dalam catur atau sekitar kubus dua kali lipat di backgammon.The
Move
kelas sedikit rumit. Saya akan mengatakan bahwa saya dapat menentukan langkah untuk bermain dengan menentukanGameState
hasil dari bermain langkah tersebut. Jadi Anda bisa membayangkan bahwa suatu langkah hanya dapat diimplementasikan sebagaiGameState
. Namun, dalam proses (misalnya) Anda dapat membayangkan bahwa jauh lebih mudah untuk menentukan langkah dengan menentukan satu titik di papan tulis. Kami inginMove
kelas kami cukup fleksibel untuk menangani semua kasus ini. Oleh karena ituMove
kelas sebenarnya akan menjadi antarmuka dengan metode yang mengambil pra-pindahGameState
dan mengembalikan pasca-pindah baruGameState
.Sekarang
RuleBook
kelas bertanggung jawab untuk mengetahui segala sesuatu tentang aturan. Ini dapat dipecah menjadi tiga hal. Perlu mengetahui apa yang awalGameState
, perlu tahu apa yang legal, dan perlu tahu apakah salah satu pemain telah menang.Anda juga bisa membuat
GameHistory
kelas untuk melacak semua gerakan yang telah dilakukan dan semuaGameStates
yang telah terjadi. Kelas baru diperlukan karena kami memutuskan bahwa satuGameState
tidak boleh bertanggung jawab untuk mengetahui semuaGameState
yang datang sebelumnya.Ini menyimpulkan kelas / antarmuka yang akan saya bahas. Anda juga memiliki
Board
kelas. Tetapi saya pikir papan di permainan yang berbeda cukup berbeda sehingga sulit untuk melihat apa yang secara umum dapat dilakukan dengan papan. Sekarang saya akan memberikan antarmuka generik dan mengimplementasikan kelas generik.Pertama adalah
GameState
. Karena kelas ini sepenuhnya tergantung pada gim tertentu, tidak adaGamestate
antarmuka atau kelas generik .Berikutnya adalah
Move
. Seperti yang saya katakan, ini dapat diwakili dengan antarmuka yang memiliki metode tunggal yang mengambil keadaan pra-pindah dan menghasilkan keadaan pasca-pindah. Berikut ini kode untuk antarmuka ini:Perhatikan bahwa ada parameter tipe. Ini karena, misalnya,
ChessMove
perlu mengetahui tentang rincian pra-langkahChessGameState
. Jadi, misalnya, deklarasi kelasChessMove
akan menjadiclass ChessMove extends Move<ChessGameState>
,di mana Anda sudah mendefinisikan
ChessGameState
kelas.Selanjutnya saya akan membahas
RuleBook
kelas generik . Ini kodenya:Sekali lagi ada parameter tipe untuk
GameState
kelas. KarenaRuleBook
seharusnya mengetahui apa itu keadaan awal, kami telah menggunakan metode untuk memberikan keadaan awal. Karena yangRuleBook
seharusnya mengetahui langkah apa yang legal, kami memiliki metode untuk menguji apakah langkah tersebut legal di negara tertentu dan memberikan daftar langkah hukum untuk negara tertentu. Akhirnya, ada metode untuk mengevaluasiGameState
. Perhatikan bahwaRuleBook
seharusnya hanya bertanggung jawab untuk menggambarkan jika salah satu atau pemain lain telah menang, tetapi tidak siapa yang berada di posisi yang lebih baik di tengah permainan. Memutuskan siapa yang berada dalam posisi yang lebih baik adalah hal yang rumit yang harus dipindahkan ke kelasnya sendiri. Oleh karena ituStateEvaluation
kelas sebenarnya hanya enum sederhana yang diberikan sebagai berikut:Terakhir, mari kita jelaskan
GameHistory
kelasnya. Kelas ini bertanggung jawab untuk mengingat semua posisi yang dicapai dalam permainan serta gerakan yang dimainkan. Hal utama yang harus dapat dilakukan adalah merekamMove
sebagai dimainkan. Anda juga dapat menambahkan fungsionalitas untuk membatalkanMove
s. Saya memiliki implementasi di bawah ini.Akhirnya, kita bisa membayangkan membuat
Game
kelas untuk mengikat semuanya. IniGame
kelas seharusnya mengekspos metode yang memungkinkan orang untuk melihat apa yang saat iniGameState
adalah, melihat siapa, jika seseorang memiliki satu, melihat apa yang bisa dimainkan bergerak, dan bermain bergerak. Saya memiliki implementasi di bawah iniPerhatikan di kelas ini bahwa
RuleBook
tidak bertanggung jawab untuk mengetahui apa arusGameState
. ItuGameHistory
pekerjaannya. Jadi merekaGame
bertanya sepertiGameHistory
apa keadaan saat ini dan memberikan informasi ini padaRuleBook
saatGame
kebutuhan untuk mengatakan apa langkah hukumnya atau jika ada yang menang.Pokoknya, inti dari jawaban ini adalah begitu Anda telah membuat penentuan yang masuk akal tentang apa yang bertanggung jawab atas masing-masing kelas, dan Anda membuat setiap kelas fokus pada sejumlah kecil tanggung jawab, dan Anda menugaskan masing-masing tanggung jawab ke kelas yang unik, kemudian kelas-kelas tersebut cenderung dipisahkan, dan semuanya menjadi mudah dikodekan. Semoga itu terlihat dari contoh kode yang saya berikan.
sumber
Dalam pengalaman saya, referensi melingkar umumnya menunjukkan bahwa desain Anda tidak dipikirkan dengan baik.
Dalam desain Anda, saya tidak mengerti mengapa RuleBook perlu "tahu" tentang Negara. Mungkin menerima Negara sebagai parameter untuk beberapa metode, tentu saja, tetapi mengapa harus tahu (yaitu sebagai variabel instan) referensi ke suatu Negara? Itu tidak masuk akal bagi saya. RuleBook tidak perlu "tahu" tentang keadaan permainan tertentu untuk melakukan tugasnya; aturan permainan tidak berubah tergantung pada kondisi permainan saat ini. Jadi Anda salah mendesainnya, atau mendesainnya dengan benar tetapi menjelaskannya dengan salah.
sumber
Ketergantungan melingkar tidak selalu merupakan masalah teknis, tetapi harus dianggap sebagai bau kode, yang biasanya merupakan pelanggaran terhadap Prinsip Tanggung Jawab Tunggal .
Ketergantungan melingkar Anda berasal dari kenyataan bahwa Anda mencoba melakukan terlalu banyak dari
State
objek Anda .Setiap objek stateful seharusnya hanya menyediakan metode yang berhubungan langsung dengan mengelola negara lokal itu. Jika membutuhkan lebih dari logika paling dasar, maka mungkin harus dipecah menjadi pola yang lebih besar. Beberapa orang memiliki pendapat berbeda tentang hal ini, tetapi sebagai aturan umum, jika Anda melakukan lebih dari sekadar getter dan setter pada data, Anda melakukan terlalu banyak.
Dalam hal ini, Anda sebaiknya memiliki
StateFactory
, yang bisa tahu tentang aRulebook
. Anda mungkin memiliki kelas pengontrol lain yang menggunakan AndaStateFactory
untuk membuat game baru.State
pasti tidak seharusnya tahuRulebook
.Rulebook
mungkin tahu tentangState
tergantung pada implementasi aturan Anda.sumber
Apakah ada kebutuhan untuk objek buku aturan untuk terikat pada keadaan permainan tertentu, atau akankah lebih masuk akal untuk memiliki objek buku aturan dengan metode yang, mengingat keadaan permainan, akan melaporkan gerakan apa yang tersedia dari keadaan itu (dan, setelah melaporkan hal itu, tidak ingat apa-apa tentang keadaan tersebut)? Kecuali jika ada sesuatu yang bisa diperoleh dengan memiliki objek yang ditanyakan tentang gerakan yang tersedia mempertahankan memori keadaan permainan, tidak perlu untuk itu tetap referensi.
Mungkin saja dalam beberapa kasus akan ada keuntungan memiliki status mempertahankan aturan-mengevaluasi objek. Jika Anda berpikir situasi seperti itu mungkin muncul, saya sarankan menambahkan kelas "wasit", dan meminta buku aturan menyediakan metode "createReferee". Berbeda dengan buku aturan, yang tidak peduli apakah itu ditanya tentang satu pertandingan, atau lima puluh, objek wasit akan mengharapkan untuk memimpin satu pertandingan. Itu tidak akan diharapkan untuk merangkum semua negara yang terkait dengan permainan yang diresmikan, tetapi bisa menyimpan informasi apa pun tentang permainan yang dianggap berguna. Jika sebuah game mendukung fungsionalitas "undo", mungkin ada baiknya jika wasit menyertakan cara untuk menghasilkan objek "snapshot" yang dapat disimpan bersama dengan status game sebelumnya; objek itu harus,
Jika beberapa penggandaan mungkin diperlukan antara aspek-aspek pemrosesan aturan dan pemrosesan-status-permainan dari kode, menggunakan objek wasit akan memungkinkan untuk membuat sambungan seperti itu keluar dari buku aturan utama dan kelas-kelas game-state. Mungkin juga memungkinkan untuk membuat aturan baru mempertimbangkan aspek-aspek keadaan permainan yang tidak akan dianggap relevan oleh kelas-permainan (misalnya jika aturan ditambahkan yang mengatakan "Objek X tidak dapat melakukan Y jika pernah ke lokasi Z ", wasit dapat diubah untuk melacak objek yang telah ke lokasi Z tanpa harus mengubah kelas permainan-negara).
sumber
Cara yang tepat untuk menangani ini adalah dengan menggunakan antarmuka. Alih-alih memiliki dua kelas yang tahu tentang satu sama lain, mintalah masing-masing kelas mengimplementasikan antarmuka dan referensi yang ada di kelas lainnya. Katakanlah Anda memiliki kelas A dan kelas B yang perlu saling referensi. Memiliki antarmuka implement kelas A dan antarmuka implement B kelas B maka Anda dapat mereferensikan antarmuka B dari kelas A dan antarmuka A dari kelas B. Kelas A dapat dari pada proyek itu sendiri, seperti halnya kelas B. Antarmuka berada dalam proyek terpisah yang kedua referensi proyek lainnya.
sumber