Jika saya ingin memprogram dalam gaya "fungsional", dengan apa saya akan mengganti antarmuka?
interface IFace
{
string Name { get; set; }
int Id { get; }
}
class Foo : IFace { ... }
Mungkin a Tuple<>
?
Tuple<Func<string> /*get_Name*/, Action<String> /*set_Name*/, Func<int> /*get_Id*/> Foo;
Satu-satunya alasan saya menggunakan antarmuka di tempat pertama adalah karena saya ingin selalu ingin properti / metode tertentu tersedia.
Sunting: Beberapa detail tentang apa yang saya pikirkan / coba.
Katakanlah, saya punya metode yang membutuhkan tiga fungsi:
static class Blarf
{
public static void DoSomething(Func<string> getName, Action<string> setName, Func<int> getId);
}
Dengan contoh Bar
saya dapat menggunakan metode ini:
class Bar
{
public string GetName();
public void SetName(string value);
public int GetId();
}
...
var bar = new Bar();
Blarf.DoSomething(bar.GetName, bar.SetName, bar.GetId);
Tapi itu agak menyebalkan karena saya harus menyebutkan bar
tiga kali dalam satu panggilan. Plus, saya tidak benar-benar berniat bagi penelepon untuk memasok fungsi dari berbagai kejadian
Blarf.DoSomething(bar1.GetName, bar2.SetName, bar3.GetId); // NO!
Dalam C #, an interface
adalah salah satu cara untuk menghadapinya; tapi itu sepertinya pendekatan yang sangat berorientasi objek. Saya bertanya-tanya apakah ada solusi yang lebih fungsional: 1) melewati kelompok fungsi bersama, dan 2) memastikan fungsi terkait satu sama lain dengan benar.
Jawaban:
Jangan memperlakukan pemrograman fungsional sebagai lapisan tipis di atas pemrograman imperatif; ada lebih dari sekedar perbedaan sintaksis.
Dalam hal ini, Anda memiliki
GetID
metode, yang menyiratkan keunikan objek. Ini bukan pendekatan yang baik untuk menulis program fungsional. Mungkin Anda bisa memberi tahu kami masalah yang Anda coba selesaikan dan kami bisa memberi Anda saran yang lebih bermakna.sumber
Haskell dan turunannya memiliki kacamata ketik yang mirip dengan antarmuka. Meskipun sepertinya Anda bertanya tentang bagaimana melakukan enkapsulasi, yang merupakan pertanyaan tentang sistem tipe. Sistem tipe hindley Milner adalah umum dalam bahasa fungsional, dan memiliki tipe data yang melakukan ini untuk Anda dalam berbagai cara di berbagai bahasa.
sumber
Ada beberapa cara untuk memungkinkan suatu fungsi menangani beberapa input.
Pertama dan paling umum: Polimorfisme Parametrik.
Ini memungkinkan fungsi bertindak pada tipe arbitrer:
Yang bagus, tetapi tidak memberi Anda pengiriman dinamis yang dimiliki antarmuka OO. Untuk Haskell ini memiliki kacamata ketik, Scala memiliki implisit, dll
Di antara kedua mekanisme ini, Anda dapat mengekspresikan semua jenis perilaku yang kompleks dan menarik pada tipe Anda.
sumber
Aturan dasar praktis adalah bahwa dalam fungsi pemrograman FP melakukan pekerjaan yang sama seperti objek dalam pemrograman OO. Anda dapat memanggil metode mereka (yah, metode "panggilan") dan mereka merespons sesuai dengan beberapa aturan internal yang dienkapsulasi. Secara khusus, setiap bahasa FP yang layak di luar sana memungkinkan Anda memiliki "variabel instan" dalam fungsi Anda dengan penutupan / pelingkupan leksikal.
Sekarang pertanyaan selanjutnya adalah apa yang Anda maksud dengan antarmuka? Salah satu pendekatan adalah menggunakan antarmuka nominal (sesuai dengan antarmuka jika ia mengatakan demikian) - pendekatan ini biasanya sangat tergantung pada bahasa apa yang Anda gunakan jadi mari kita tinggalkan untuk yang terakhir. Cara lain untuk mendefinisikan antarmuka adalah cara struktural, melihat parameter apa yang diterima dan dikembalikan. Ini adalah jenis antarmuka yang cenderung Anda lihat dalam bahasa yang dinamis dan diketik dengan bebek dan sangat cocok dengan semua FP: antarmuka hanyalah jenis parameter input untuk fungsi kami dan jenis yang dikembalikan sehingga semua fungsi sesuai dengan jenis yang benar sesuai dengan antarmuka!
Oleh karena itu, cara paling mudah untuk merepresentasikan objek yang cocok dengan antarmuka adalah dengan hanya memiliki sekelompok fungsi. Anda biasanya menyiasati keburukan dari melewatkan fungsi secara terpisah dengan mengemasnya dalam semacam catatan:
Menggunakan fungsi-fungsi telanjang atau catatan-catatan fungsi akan sangat membantu dalam menyelesaikan sebagian besar masalah umum Anda dengan cara "bebas lemak" tanpa berton-ton boilerplate. Jika Anda membutuhkan sesuatu yang lebih maju dari itu, terkadang bahasa memberi Anda fitur tambahan. Salah satu contoh yang disebutkan orang adalah kelas tipe Haskell. Jenis kelas pada dasarnya mengaitkan jenis dengan salah satu catatan fungsi dan memungkinkan Anda menulis hal-hal sehingga kamus implisit dan secara otomatis diteruskan ke fungsi dalam yang sesuai.
Satu hal penting yang perlu diperhatikan tentang typeclasses adalah bahwa kamus dikaitkan dengan jenis, dan bukan dengan nilai-nilai (seperti apa yang terjadi dalam kamus dan versi OO). Ini berarti Anda bahwa sistem tipe tidak memungkinkan Anda mencampur "tipe" [1]. Jika Anda ingin daftar "blargables" atau fungsi biner yang diambil ke blargables maka typeclasses akan membatasi semuanya menjadi jenis yang sama sementara pendekatan kamus akan membiarkan Anda memiliki blargables dari asal yang berbeda (versi mana yang lebih baik banyak tergantung pada apa yang Anda berada perbuatan)
[1] Ada beberapa cara canggih untuk melakukan "tipe eksistensial" tetapi biasanya tidak sepadan dengan masalahnya.
sumber
Saya pikir ini akan menjadi spesifik bahasa. Saya berasal dari latar belakang lispy. Dalam banyak kasus antarmuka dengan keadaan memecah model fungsional ke tingkat tertentu. Jadi CLOS, misalnya, adalah tempat LISP kurang fungsional dan lebih dekat ke bahasa imperatif. Secara umum, parameter fungsi yang diperlukan yang dikombinasikan dengan metode level yang lebih tinggi mungkin adalah yang Anda cari.
sumber