Catatan awal:
Pertanyaan ini ditutup setelah beberapa pengeditan karena saya tidak memiliki terminologi yang tepat untuk menyatakan secara akurat apa yang saya cari. Sam Tobin-Hochstadt kemudian memposting komentar yang membuat saya mengenali persis apa itu: bahasa pemrograman yang mendukung tipe persimpangan untuk nilai-nilai fungsi kembali.
Sekarang pertanyaan telah dibuka kembali, saya telah memutuskan untuk memperbaikinya dengan menulis ulang dengan (mudah-mudahan) cara yang lebih tepat. Karenanya, beberapa jawaban dan komentar di bawah mungkin tidak lagi masuk akal karena merujuk pada suntingan sebelumnya. (Silakan lihat riwayat edit pertanyaan dalam kasus semacam itu.)
Apakah ada bahasa pemrograman yang populer secara statis & sangat diketik (seperti Haskell, Java generik, C #, F #, dll.) Yang mendukung tipe persimpangan untuk nilai pengembalian fungsi? Jika ya, yang mana, dan bagaimana?
(Jika saya jujur, saya akan sangat senang melihat seseorang menunjukkan cara bagaimana mengekspresikan jenis persimpangan dalam bahasa umum seperti C # atau Java.)
Saya akan memberikan contoh cepat tentang apa jenis persimpangan mungkin terlihat, menggunakan beberapa pseudocode mirip dengan C #:
interface IX { … }
interface IY { … }
interface IB { … }
class A : IX, IY { … }
class B : IX, IY, IB { … }
T fn() where T : IX, IY
{
return … ? new A()
: new B();
}
Yaitu, fungsi fn
mengembalikan sebuah instance dari beberapa tipe T
, di mana si penelepon hanya tahu bahwa ia mengimplementasikan antarmuka IX
dan IY
. (Yaitu, tidak seperti dengan obat generik, penelepon tidak dapat memilih tipe konkret T
- fungsinya. Dari sini saya kira itu T
sebenarnya bukan tipe universal, tetapi tipe eksistensial.)
PS: Saya sadar bahwa seseorang dapat dengan mudah mendefinisikan interface IXY : IX, IY
dan mengubah tipe pengembalian fn
ke IXY
. Namun, itu bukan hal yang benar-benar sama, karena sering kali Anda tidak dapat menghubungkan antarmuka tambahan IXY
ke tipe A
yang sebelumnya didefinisikan yang hanya mengimplementasikan IX
dan IY
secara terpisah.
Catatan kaki: Beberapa sumber tentang tipe persimpangan:
Artikel Wikipedia untuk "Tipe sistem" memiliki subbagian tentang jenis persimpangan .
Laporan oleh Benjamin C. Pierce (1991), "Pemrograman Dengan Jenis Persimpangan, Jenis Serikat, dan Polimorfisme"
David P. Cunningham (2005), "Jenis titik-temu dalam praktik" , yang berisi studi kasus tentang bahasa Forsythe, yang disebutkan dalam artikel Wikipedia.
Pertanyaan A Stack Overflow, "jenis Union dan jenis persimpangan" yang mendapat beberapa jawaban yang baik, di antaranya satu ini yang memberikan contoh pseudocode dari jenis persimpangan sama dengan saya di atas.
T
mendefinisikan tipe, bahkan jika itu hanya didefinisikan dalam deklarasi fungsi sebagai "beberapa tipe yang meluas / mengimplementasikanIX
danIY
". Fakta bahwa nilai pengembalian aktual adalah kasus khusus yang (A
atauB
masing - masing) bukanlah sesuatu yang istimewa di sini, Anda bisa mencapainya dengan menggunakanObject
alih-alihT
.T
sebagai antarmukaI
saat mengimplementasikan semua metode antarmuka, tetapi tidak menyatakan antarmuka itu".Jawaban:
Scala memiliki tipe persimpangan penuh yang dibangun ke dalam bahasa:
sumber
Sebenarnya, jawaban yang jelas adalah: Jawa
Meskipun mungkin mengejutkan Anda mengetahui bahwa Java mendukung tipe persimpangan ... itu memang melalui operator terikat tipe "&". Sebagai contoh:
Lihat tautan ini pada beberapa batasan tipe di Java, dan juga ini dari Java API.
sumber
<T extends IX & IY> T f() { if(condition) return new A(); else return new B(); }
. Dan bagaimana Anda memanggil fungsi dalam kasus seperti itu? A atau B tidak dapat muncul di situs panggilan, karena Anda tidak tahu mana yang akan Anda dapatkan.Pertanyaan awal meminta "tipe ambigu". Untuk itu jawabannya adalah:
Tipe ambigu, jelas tidak ada. Penelepon perlu tahu apa yang akan mereka dapatkan, jadi itu tidak mungkin. Semua bahasa apa pun dapat kembali adalah tipe dasar, antarmuka (mungkin dihasilkan secara otomatis seperti pada tipe persimpangan) atau tipe dinamis (dan tipe dinamis pada dasarnya hanya ketik dengan panggilan nama, dapatkan, dan atur metode).
Antarmuka yang disimpulkan:
Jadi pada dasarnya Anda ingin mengembalikan antarmuka
IXY
yang berasalIX
danIY
meskipun antarmuka itu tidak dideklarasikan di salah satuA
atauB
, mungkin karena tidak dideklarasikan ketika tipe tersebut didefinisikan. Dalam hal itu:A
danB
atau tipe persimpanganIX
danIY
) itu sendiri.PS A sangat bahasa diketik adalah satu di mana sebuah objek dari tipe yang diberikan tidak dapat diperlakukan sebagai objek jenis lain, sementara lemah bahasa diketik adalah salah satu yang memiliki pemain menafsirkan. Jadi semua bahasa yang diketik secara dinamis diketik dengan kuat , sementara bahasa yang diketik dengan lemah adalah assembly, C dan C ++, ketiganya diketik secara statis .
sumber
Go Bahasa Pemrograman jenis memiliki ini, tapi hanya untuk jenis antarmuka.
Di Go, tipe apa pun yang metode yang benar didefinisikan secara otomatis mengimplementasikan antarmuka, sehingga keberatan dalam PS Anda tidak berlaku. Dengan kata lain, buat saja sebuah antarmuka yang memiliki semua operasi dari jenis antarmuka yang akan digabungkan (yang ada sintaksinya sederhana) dan semuanya hanya berfungsi.
Sebuah contoh:
sumber
Anda mungkin dapat melakukan apa yang Anda inginkan dengan menggunakan tipe eksistensial terbatas, yang dapat dikodekan dalam bahasa apa pun dengan generik dan polimorfisme terikat, misalnya C #.
Jenis pengembalian akan menjadi seperti (dalam kode psuedo)
IAB = exists T. T where T : IA, IB
atau dalam C #:
Catatan: Saya belum menguji ini.
Intinya adalah bahwa
IAB
harus dapat menerapkan IABFunc untuk semua jenis pengembalianR
, danIABFunc
harus mampu bekerja padaT
subtipe mana sajaIA
danIB
.Maksudnya
DefaultIAB
adalah hanya untuk membungkus yang adaT
subtipeIA
danIB
. Perhatikan bahwa ini berbeda dariIAB : IA, IB
di Anda yangDefaultIAB
selalu dapat ditambahkan ke yang sudah ada diT
kemudian hari.Referensi:
sumber
Apply
untuk dipanggil padanya. Masalah besar adalah bahwa tidak ada cara untuk menggunakan fungsi anonim untuk mengimplementasikan antarmuka, jadi konstruksi seperti itu akhirnya menjadi rasa sakit yang nyata untuk digunakan.TypeScript adalah bahasa yang diketik lain yang mendukung jenis persimpangan
T & U
(bersama dengan jenis serikatT | U
). Berikut adalah contoh yang dikutip dari halaman dokumentasi mereka tentang tipe lanjutan :sumber
Ceylon memiliki dukungan penuh untuk jenis persatuan dan persimpangan kelas satu .
Anda menulis tipe gabungan sebagai
X | Y
dan tipe persimpangan sebagaiX & Y
.Bahkan lebih baik, Ceylon menghadirkan banyak alasan canggih tentang jenis-jenis ini, termasuk:
Consumer<X>&Consumer<Y>
adalah tipe yang sama sepertiConsumer<X|Y>
jikaConsumer
contravarian diX
, danObject&Null
adalah tipe yang sama denganNothing
, tipe bawah.sumber
Fungsi-fungsi C ++ semuanya memiliki tipe pengembalian tetap, tetapi jika mereka mengembalikan pointer, pointer dapat, dengan batasan, menunjuk ke tipe yang berbeda.
Contoh:
Perilaku pointer yang dikembalikan akan tergantung pada
virtual
fungsi apa yang didefinisikan, dan Anda dapat melakukan pengecekan downcast dengan, katakanlah,Base * foo = function(...);dynamic_cast<Derived1>(foo)
.Begitulah cara polimorfisme bekerja di C ++.
sumber
any
atauvariant
jenis, seperti yang disediakan template boost. Dengan demikian, batasannya tidak tinggal.class Base1{}; class Base2{}; class Derived1 : public Base1, public Base2 {}; class Derived2 : public Base1, public Base2 {}
... sekarang jenis apa yang dapat kita tentukan yang memungkinkan untuk kembaliDerived1
atauDerived2
tidakBase1
juga tidakBase2
langsung?Python
Ini sangat, sangat sangat diketik.
Tetapi tipe ini tidak dideklarasikan ketika sebuah fungsi dibuat, jadi objek yang dikembalikan "ambigu".
Dalam pertanyaan spesifik Anda, istilah yang lebih baik mungkin "Polimorfik". Itu kasus penggunaan umum dalam Python adalah untuk mengembalikan jenis varian yang mengimplementasikan antarmuka umum.
Karena Python diketik dengan kuat, objek yang dihasilkan akan menjadi turunan dari
This
danThat
dan tidak dapat (dengan mudah) dipaksa atau dilemparkan ke jenis objek lain.sumber