Pemrograman fungsional dibandingkan dengan OOP dengan kelas

32

Saya telah tertarik pada beberapa konsep pemrograman fungsional belakangan ini. Saya telah menggunakan OOP untuk beberapa waktu sekarang. Saya dapat melihat bagaimana saya akan membangun aplikasi yang cukup kompleks di OOP. Setiap objek akan tahu bagaimana melakukan hal-hal yang dilakukan objek. Atau apa pun yang dilakukan kelas orang tua juga. Jadi saya hanya bisa mengatakan Person().speak()untuk membuat orang itu berbicara.

Tetapi bagaimana saya melakukan hal serupa dalam pemrograman fungsional? Saya melihat bagaimana fungsi adalah item kelas satu. Tetapi fungsi itu hanya melakukan satu hal spesifik. Apakah saya hanya memiliki say()metode yang mengambang dan menyebutnya dengan Person()argumen yang setara sehingga saya tahu hal seperti apa yang mengatakan sesuatu?

Jadi saya bisa melihat hal-hal sederhana, bagaimana saya bisa melakukan perbandingan OOP dan objek dalam pemrograman fungsional, sehingga saya dapat memodulasi dan mengatur basis kode saya?

Sebagai referensi, pengalaman utama saya dengan OOP adalah Python, PHP, dan beberapa C #. Bahasa yang saya lihat yang memiliki fitur fungsional adalah Scala dan Haskell. Meskipun saya condong ke arah Scala.

Contoh Dasar (Python):

Animal(object):
    def say(self, what):
        print(what)

Dog(Animal):
    def say(self, what):
        super().say('dog barks: {0}'.format(what))

Cat(Animal):
    def say(self, what):
        super().say('cat meows: {0}'.format(what))

dog = Dog()
cat = Cat()
dog.say('ruff')
cat.say('purr')
Skift
sumber
Scala dirancang sebagai OOP + FP, jadi Anda tidak perlu memilih
Karthik T
1
Ya saya sadar, tetapi saya juga ingin tahu karena alasan intelektual. Saya tidak dapat menemukan apa pun pada objek yang ekuivalen dalam bahasa fungsional. Adapun scala, saya masih ingin tahu kapan / di mana / bagaimana saya harus menggunakan fungsional lebih dari oop, tapi IMHO itu adalah pertanyaan lain.
Skift
2
"Terutama terlalu ditekankan, IMO adalah gagasan bahwa kita tidak mempertahankan status.": Ini adalah gagasan yang salah. Tidak benar bahwa FP tidak menggunakan status, melainkan FP menangani keadaan dengan cara yang berbeda (misalnya monad di Haskell atau tipe unik di Bersihkan).
Giorgio
1
duplikat yang mungkin dari Bagaimana mengatur program fungsional
Doc Brown
3
kemungkinan duplikat Pemrograman Fungsional vs OOP
Caleb

Jawaban:

21

Apa yang sebenarnya Anda tanyakan di sini adalah bagaimana melakukan Polimorfisme dalam bahasa fungsional, yaitu cara membuat fungsi yang berperilaku berbeda berdasarkan argumen mereka.

Perhatikan argumen pertama untuk suatu fungsi biasanya setara dengan "objek" di OOP, tetapi dalam bahasa fungsional Anda biasanya ingin memisahkan fungsi dari data, sehingga "objek" cenderung menjadi nilai data yang murni (tidak berubah).

Bahasa fungsional secara umum menyediakan berbagai opsi untuk mencapai polimorfisme:

  • Sesuatu seperti metode multimetode yang memanggil fungsi berbeda berdasarkan memeriksa argumen yang diberikan. Hal ini dapat dilakukan pada jenis argumen pertama (yang secara efektif sama dengan perilaku sebagian besar bahasa OOP), tetapi juga dapat dilakukan pada atribut lain dari argumen.
  • Prototipe / struktur data seperti objek yang berisi fungsi kelas satu sebagai anggota . Jadi Anda bisa menanamkan fungsi "katakan" di dalam struktur data anjing dan kucing Anda. Secara efektif Anda telah membuat kode bagian dari data.
  • Pencocokan pola - di mana logika pencocokan pola dibangun ke dalam definisi fungsi, dan memastikan perilaku yang berbeda untuk parameter yang berbeda. Umum di Haskell.
  • Percabangan / ketentuan - setara dengan jika / orang lain klausa dalam OOP. Mungkin tidak bisa sangat diperluas, tetapi masih bisa sesuai dalam banyak kasus ketika Anda memiliki seperangkat nilai yang mungkin terbatas (misalnya apakah fungsi melewati angka atau string atau null?)

Sebagai contoh, berikut ini adalah implementasi Clojure dari masalah Anda menggunakan metode multimetode:

;; define a multimethod, that dispatched on the ":type" keyword
(defmulti say :type)  

;; define specific methods for each possible value of :type. You can add more later
(defmethod say :cat [animal what] (println (str "Car purrs: " what)))
(defmethod say :dog [animal what] (println (str "Dog barks: " what)))
(defmethod say :default [animal what] (println (str "Unknown noise: " what)))

(say {:type :dog} "ruff")
=> Dog barks: ruff

(say {:type :ape} "ook")
=> Unknown noise: ook

Perhatikan bahwa perilaku ini tidak memerlukan kelas eksplisit untuk didefinisikan: peta reguler berfungsi dengan baik. Fungsi pengiriman (: ketikkan dalam hal ini) dapat berupa fungsi sembarang argumen.

mikera
sumber
Tidak 100% jelas, tetapi cukup untuk melihat ke mana Anda pergi. Saya bisa melihat ini sebagai kode 'binatang' dalam file yang diberikan. Juga bagian pada percabangan / kondisi juga bagus. Saya tidak menganggap itu sebagai alternatif untuk if / else.
Skift
11

Ini bukan jawaban langsung, juga belum tentu 100% akurat karena saya bukan ahli bahasa fungsional. Namun dalam kedua kasus, saya akan berbagi dengan Anda pengalaman saya ...

Sekitar setahun yang lalu saya berada di kapal yang sama seperti Anda. Saya telah melakukan C ++ dan C # dan semua desain saya selalu sangat berat di OOP. Saya pernah mendengar tentang bahasa FP, membaca beberapa info online, membolak-balik buku F # tetapi masih belum bisa memahami bagaimana bahasa FP dapat menggantikan OOP atau berguna secara umum karena kebanyakan contoh yang saya lihat terlalu sederhana.

Bagi saya "terobosan" datang ketika saya memutuskan untuk belajar python. Saya mengunduh python, lalu pergi ke homepage proyek euler dan baru saja mulai melakukan satu masalah demi satu. Python tidak harus merupakan bahasa FP dan Anda tentu dapat membuat kelas di dalamnya, tetapi dibandingkan dengan C ++ / Java / C #, ia memiliki lebih banyak konstruksi FP, jadi ketika saya mulai bermain dengannya, saya membuat keputusan sadar untuk tidak mendefinisikan sebuah kelas kecuali saya benar-benar harus melakukannya.

Apa yang saya temukan menarik tentang Python adalah betapa mudah dan alami untuk mengambil fungsi dan "menjahit" mereka untuk membuat fungsi yang lebih kompleks dan pada akhirnya masalah Anda masih diselesaikan dengan memanggil satu fungsi.

Anda menunjukkan bahwa ketika coding Anda harus mengikuti prinsip tanggung jawab tunggal dan itu benar-benar benar. Tetapi hanya karena fungsi bertanggung jawab untuk satu tugas, tidak berarti itu hanya dapat melakukan minimum mutlak. Di FP, Anda masih memiliki level abstraksi. Jadi fungsi tingkat tinggi Anda masih bisa melakukan "satu" hal tetapi mereka dapat mendelegasikan ke fungsi tingkat yang lebih rendah untuk mengimplementasikan detail yang lebih baik tentang bagaimana "satu" hal itu tercapai.

Kuncinya dengan FP adalah Anda tidak memiliki efek samping. Selama Anda memperlakukan aplikasi sebagai transformasi data sederhana dengan set input dan output yang ditentukan, Anda dapat menulis kode FP yang akan memenuhi apa yang Anda butuhkan. Jelas tidak semua aplikasi cocok dengan cetakan ini, tetapi begitu Anda mulai melakukannya, Anda akan terkejut betapa banyak aplikasi yang cocok. Dan di sinilah saya pikir Python, F # atau Scala bersinar karena mereka memberi Anda konstruksi FP tetapi ketika Anda perlu mengingat keadaan Anda dan "memperkenalkan efek samping" Anda selalu dapat mengandalkan teknik OOP yang benar dan mencoba.

Sejak itu, saya telah menulis sejumlah besar kode python sebagai utilitas dan skrip pembantu lainnya untuk pekerjaan internal dan beberapa di antaranya ditingkatkan cukup jauh tetapi dengan mengingat prinsip-prinsip PADAT dasar, sebagian besar kode itu masih keluar sangat dapat dipertahankan dan fleksibel. Sama seperti di OOP antarmuka Anda adalah kelas dan Anda memindahkan kelas saat Anda refactor dan / atau menambahkan fungsionalitas, di FP Anda melakukan hal yang persis sama dengan fungsi.

Minggu lalu saya mulai coding di Java dan sejak itu, hampir setiap hari saya diingatkan bahwa ketika di OOP, saya harus mengimplementasikan antarmuka dengan mendeklarasikan kelas dengan metode yang mengesampingkan fungsi, dalam beberapa kasus saya bisa mencapai hal yang sama di Python menggunakan ekspresi lambda sederhana, misalnya, 20-30 baris kode yang saya tulis untuk memindai direktori, sudah 1-2 baris dalam Python dan tidak ada kelas.

FP sendiri adalah bahasa tingkat yang lebih tinggi. Dalam Python (maaf, satu-satunya pengalaman FP saya) saya bisa mengumpulkan daftar pemahaman dalam pemahaman daftar lain dengan lambdas dan hal-hal lain yang dilemparkan ke dalam dan semuanya hanya akan 3-4 baris kode. Dalam C ++, saya benar-benar dapat mencapai hal yang sama, tetapi karena C ++ adalah level yang lebih rendah, saya harus menulis lebih banyak kode daripada 3-4 baris dan ketika jumlah baris meningkat, pelatihan SRP saya akan dimulai dan saya akan mulai berpikir tentang cara membagi kode menjadi bagian-bagian yang lebih kecil (yaitu lebih banyak fungsi). Tetapi untuk kepentingan kelestarian dan menyembunyikan detail implementasi, saya akan menempatkan semua fungsi itu ke dalam kelas yang sama dan menjadikannya pribadi. Dan begitulah ... Saya baru saja membuat kelas sedangkan di python saya akan menulis "kembali (.... lambda x: ... ....)"

DXM
sumber
Ya itu tidak langsung menjawab pertanyaan, tetapi masih respons yang bagus. ketika saya menulis skrip atau paket yang lebih kecil dengan python, saya juga tidak selalu menggunakan kelas. berkali-kali hanya memilikinya dalam format paket sangat cocok. terutama jika saya tidak perlu negara. Saya juga setuju bahwa pemahaman daftar juga sangat berguna. Sejak membaca FP, saya menyadari betapa jauh lebih kuatnya mereka. yang kemudian membuat saya ingin belajar lebih banyak tentang FP, dibandingkan dengan OOP.
Skift
Jawaban yang bagus Berbicara kepada semua orang yang berdiri di sisi kolam fungsional tetapi tidak yakin apakah akan mencelupkan kaki mereka ke dalam air
Robben_Ford_Fan_boy
Dan Ruby ... Salah satu filosofi desainnya berpusat pada metode mengambil blok kode sebagai argumen, biasanya yang opsional. Dan mengingat sintaksis yang bersih berpikir dan mengkode dengan cara ini mudah. Sulit untuk berpikir dan menulis seperti ini di C #. C # writ secara fungsional adalah bertele-tele dan membingungkan, rasanya disemir ke dalam bahasa. Saya suka bahwa Ruby membantu berpikir secara fungsional lebih mudah, untuk melihat potensi di kotak pemikiran C # saya. Dalam analisis akhir saya melihat fungsional dan OO sebagai pelengkap; Saya akan mengatakan Ruby tentu saja berpikir begitu.
radarbob
8

Di Haskell, yang terdekat dengan Anda adalah "kelas". Kelas ini meskipun tidak sama dengan kelas di Java dan C ++ , akan bekerja untuk apa yang Anda inginkan dalam kasus ini.

Dalam kasus Anda ini adalah bagaimana kode Anda akan terlihat.

Hewan kelas mana 
say :: String -> sound 

Kemudian Anda dapat memiliki tipe data individual mengadaptasi metode ini.

Misalnya Anjing Hewan di mana
say s = "bark" ++ s 

Sunting: - Sebelum Anda dapat mengkhususkan mengatakan untuk Anjing, Anda perlu memberi tahu sistem bahwa Anjing adalah binatang.

data Dog = \ - sesuatu di sini - \ (berasal Hewan)

EDIT: - Untuk Wilq.
Sekarang jika Anda ingin menggunakan katakan dalam fungsi say foo, Anda harus memberi tahu haskell bahwa foo hanya dapat bekerja dengan Animal.

foo :: (Animal a) => a -> String -> String
foo a str = katakanlah str 

sekarang jika Anda memanggil anjing dengan anjing itu akan menggonggong, jika Anda menelepon dengan kucing itu akan mengeong.

main = do 
misalkan d = dog (\ - parameter cstr - \)
    c = kucing  
dalam acara $ foo d "Hello World"

Anda sekarang tidak dapat memiliki definisi fungsi lainnya. Jika say disebut dengan sesuatu yang bukan hewan, itu akan menyebabkan kesalahan kompilasi.

Manoj R
sumber
Aku harus benar-benar lebih pada haskell untuk memahami ini sepenuhnya, tetapi saya pikir saya mendapatkan intisari dari itu. Saya masih penasaran bagaimana ini akan sejalan dengan basis kode yang lebih kompleks.
Skift
nitpick Animal harus dikapitalisasi
Daniel Gratzer
1
Bagaimana fungsi say tahu bahwa Anda memanggilnya pada Dog jika hanya membutuhkan sebuah String? Dan bukankah "memperoleh" hanya untuk beberapa kelas bawaan?
WilQu
6

Bahasa fungsional menggunakan 2 konstruksi untuk mencapai polimorfisme:

  • Fungsi urutan pertama
  • Generik

Membuat kode polimorfik dengan yang sama sekali berbeda dari bagaimana OOP menggunakan metode pewarisan dan virtual. Meskipun keduanya mungkin tersedia dalam bahasa OOP favorit Anda (seperti C #), sebagian besar bahasa fungsional (seperti Haskell) menendang hingga sebelas. Jarang berfungsi sebagai non-generik dan sebagian besar fungsi memiliki fungsi sebagai parameter.

Sulit untuk menjelaskan seperti ini dan akan membutuhkan banyak waktu Anda untuk mempelajari cara baru ini. Tetapi untuk melakukan ini, Anda harus benar-benar melupakan OOP, karena itu bukan cara kerjanya di dunia fungsional.

Euforia
sumber
2
OOP adalah tentang polimorfisme. Jika Anda mengira OOP memiliki fungsi yang terkait dengan data Anda, maka Anda tidak tahu apa-apa tentang OOP.
Euforia
4
polimorfisme hanyalah salah satu aspek dari OOP, dan saya pikir bukan yang ditanyakan oleh OP.
Doc Brown
2
Polimorfisme adalah aspek kunci dari OOP. Segala sesuatu yang lain ada untuk mendukungnya. OOP tanpa metode pewarisan / virtual hampir persis sama dengan pemrograman prosedural.
Euforia
1
@ErikReppen Jika "terapkan antarmuka" tidak sering dibutuhkan, maka Anda tidak melakukan OOP. Juga, Haskell memiliki modul juga.
Euforia
1
Anda tidak selalu membutuhkan antarmuka. Tetapi mereka sangat berguna ketika Anda membutuhkannya. Dan IMO bagian penting lainnya dari OOP. Sedangkan untuk modul masuk Haskell, saya pikir ini mungkin paling dekat dengan OOP untuk bahasa fungsional, sejauh menyangkut organisasi kode. Setidaknya dari apa yang saya baca sejauh ini. Saya tahu mereka masih sangat berbeda.
Skift
0

itu benar-benar tergantung pada apa yang ingin Anda capai.

jika Anda hanya perlu cara untuk mengatur perilaku berdasarkan kriteria selektif, Anda dapat menggunakan misalnya kamus (tabel hash) dengan objek-fungsi. dalam python bisa berupa sesuatu di sepanjang baris:

def bark(what):
    print "barks: {0}".format(what) 

def meow(what):
    print "meows: {0}".format(what)

def climb(how):
    print "climbs: {0}".format(how)

if __name__ == "__main__":
    animals = {'dog': {'say': bark},
               'cat': {'say': meow,
                       'climb': climb}}
    animals['dog']['say']("ruff")
    animals['cat']['say']("purr")
    animals['cat']['climb']("well")

Namun perhatikan, bahwa (a) tidak ada 'kejadian' anjing atau kucing dan (b) Anda harus melacak 'jenis' objek Anda sendiri.

seperti misalnya: pets = [['martin','dog','grrrh'], ['martha', 'cat', 'zzzz']]. maka Anda bisa melakukan pemahaman daftar seperti[animals[pet[1]]['say'](pet[2]) for pet in pets]

kr1
sumber
0

Bahasa OO dapat digunakan sebagai pengganti bahasa tingkat rendah kadang-kadang untuk berinteraksi langsung dengan mesin. C ++ Tentu saja, tetapi bahkan untuk C # ada adapter dan semacamnya. Meskipun menulis kode untuk mengontrol bagian-bagian mekanik dan memiliki kontrol menit terhadap memori yang terbaik disimpan sedekat mungkin dengan level rendah. Tetapi jika pertanyaan ini terkait dengan perangkat lunak Berorientasi Objek saat ini seperti Line Of Business, aplikasi web, IOT, Layanan Web, dan sebagian besar aplikasi yang digunakan secara massal, maka ...

Jawab, jika berlaku

Pembaca mungkin mencoba bekerja dengan Arsitektur Berorientasi Layanan (SOA). Yaitu, DDD, N-Layered, N-Tiered, Hexagonal, apa pun. Saya belum melihat aplikasi bisnis besar yang secara efisien menggunakan OO "Tradisional" (Rekaman Aktif atau Model Kaya) seperti yang dijelaskan pada tahun 70-an dan 80-an dalam dekade terakhir +. (Lihat Catatan 1)

Kesalahannya bukan pada OP, tetapi ada beberapa masalah dengan pertanyaan itu.

  1. Contoh yang Anda berikan hanya untuk menunjukkan polimorfisme, itu bukan kode produksi. Terkadang contoh persis seperti itu diambil secara harfiah.

  2. Dalam FP dan SOA, Data dipisahkan dari Business Logic. Yaitu, Data dan Logika tidak berjalan bersama. Logika masuk ke Layanan, dan Data (Model Domain) tidak memiliki perilaku Polimorfik (Lihat Catatan 2).

  3. Layanan dan Fungsi dapat bersifat Polimorfik. Di FP, Anda sering melewatkan fungsi sebagai parameter ke fungsi lain alih-alih nilai. Anda dapat melakukan hal yang sama dalam Bahasa OO dengan jenis-jenis seperti Callable atau Func, tetapi tidak merajalela (Lihat Catatan 3). Dalam FP dan SOA, Model Anda bukan Polimorfik, hanya Layanan / Fungsi Anda. (Lihat Catatan 4)

  4. Ada contoh hardcoding yang buruk dalam contoh itu. Saya tidak hanya berbicara tentang benang merah "gonggongan anjing". Saya juga berbicara tentang CatModel dan DogModel sendiri. Apa yang terjadi ketika Anda ingin menambahkan Domba? Anda harus masuk ke kode Anda dan membuat kode baru? Mengapa? Dalam kode produksi, saya lebih suka melihat AnimalModel dengan propertinya. Paling buruk, AmphibianModel dan FowlModel jika properti dan penanganannya sangat berbeda.

Inilah yang saya harapkan untuk melihat dalam bahasa "OO" saat ini:

public class Animal
{
    public int AnimalID { get; set; }
    public int LegCount { get; set; }
    public string Name { get; set; }
    public string WhatISay { get; set; }
}

public class AnimalService : IManageAnimals
{
    private IPersistAnimals _animalRepo;
    public AnimalService(IPersistAnimals animalRepo) { _animalRepo = animalRepo; }

    public List<Animal> GetAnimals() => _animalRepo.GetAnimals();

    public string WhatDoISay(Animal animal)
    {
        if (!string.IsNullOrWhiteSpace(animal.WhatISay))
            return animal.WhatISay;

        return _animalRepo.GetAnimalNoise(animal.AnimalID);
    }
}

Aliran dasar

Bagaimana Anda berpindah dari Kelas di OO ke Pemrograman Fungsional? Seperti yang orang lain katakan; Anda bisa, tetapi sebenarnya tidak. Poin di atas adalah untuk menunjukkan bahwa Anda seharusnya tidak menggunakan Kelas (dalam pengertian tradisional dunia) saat melakukan Java dan C #. Setelah Anda bisa menulis kode dalam Arsitektur Berorientasi Layanan (DDD, Layered, Tiered, Hexagonal, apa pun), Anda akan selangkah lebih dekat ke Fungsional karena Anda memisahkan Data Anda (Model Domain) Dari Fungsi Logis Anda (Layanan).

Bahasa OO selangkah lebih dekat ke FP

Anda bahkan mungkin membawanya sedikit lebih jauh dan membagi Layanan SOA Anda menjadi dua jenis.

Opsional Kelas Tipe 1 : Layanan Implementasi Antarmuka Umum untuk Titik Masuk. Ini akan menjadi Entry Point "tidak murni" yang dapat memanggil fungsionalitas lain "Murni" atau "Tidak Murni". Ini mungkin Poin Masuk Anda dari API ISTIRAHAT.

Opsional Kelas Tipe 2 : Layanan Logika Bisnis Murni. Ini adalah Kelas Statis yang memiliki fungsi "Murni". Dalam FP, "Murni" berarti tidak ada efek samping. Itu tidak secara eksplisit mengatur Negara atau Kegigihan di mana saja. (Lihat Catatan 5)

Jadi, ketika Anda memikirkan Kelas dalam Bahasa Berorientasi Objek, yang digunakan dalam Arsitektur Berorientasi Layanan, itu tidak hanya menguntungkan Kode OO Anda, itu mulai membuat Pemrograman Fungsional tampak sangat mudah dimengerti.

Catatan

Catatan 1 : Desain Berorientasi Objek "Kaya" atau "Rekaman Aktif" Asli masih ada. Ada BANYAK kode warisan seperti itu ketika orang "melakukannya dengan benar" satu dekade lalu atau lebih. Terakhir kali saya melihat kode semacam itu (dilakukan dengan benar) berasal dari video game Codebase di C ++ Di mana mereka mengendalikan memori dengan tepat dan memiliki ruang yang sangat terbatas. Bukan untuk mengatakan FP dan Arsitektur Berorientasi Layanan adalah binatang dan tidak boleh mempertimbangkan perangkat keras. Tetapi mereka menempatkan kemampuan untuk terus berubah, dipelihara, memiliki ukuran data variabel, dan aspek lainnya sebagai prioritas. Dalam video game dan AI mesin, Anda mengontrol sinyal dan data dengan sangat tepat.

Catatan 2 : Model Domain tidak memiliki Perilaku Polimorfik, juga tidak memiliki Ketergantungan Eksternal. Mereka "Terisolasi". Itu tidak berarti mereka harus 100% Anemik. Mereka dapat memiliki banyak logika yang terkait dengan konstruksi mereka dan perubahan properti yang bisa berubah, jika itu berlaku. Lihat DDD "Nilai Objek" dan Entitas oleh Eric Evans dan Mark Seemann.

Catatan 3 : Linq dan Lambda sangat umum. Tetapi ketika pengguna membuat fungsi baru, mereka jarang menggunakan Func atau Callable sebagai parameter, sedangkan di FP akan aneh melihat aplikasi tanpa fungsi mengikuti pola itu.

Catatan 4 : Tidak membingungkan Polimorfisme dengan Warisan. CatModel mungkin mewarisi AnimalBase untuk menentukan Properties mana yang biasanya dimiliki Animal. Tapi seperti yang saya tunjukkan, Model seperti ini adalah Code Smell . Jika Anda melihat pola ini, Anda dapat mempertimbangkan memecahnya dan mengubahnya menjadi data.

Catatan 5 : Fungsi murni dapat (dan melakukan) menerima fungsi sebagai parameter. Fungsi yang masuk mungkin tidak murni, tetapi mungkin murni. Untuk tujuan pengujian, itu akan selalu murni. Tetapi dalam produksi, meskipun diperlakukan sebagai murni, mungkin mengandung efek samping. Itu tidak mengubah fakta bahwa fungsi murni itu murni. Padahal fungsi parameternya mungkin tidak murni. Tidak membingungkan! : D

Suamere
sumber
-2

Anda bisa melakukan sesuatu seperti ini .. php

    function say($whostosay)
    {
        if($whostosay == 'cat')
        {
             return 'purr';
        }elseif($whostosay == 'dog'){
             return 'bark';
        }else{
             //do something with errors....
        }
     }

     function speak($whostosay)
     {
          return $whostosay .'\'s '.say($whostosay);
     }
     echo speak('cat');
     >>>cat's purr
     echo speak('dog');
     >>>dogs's bark
Michael Dennis
sumber
1
Saya belum memberikan suara negatif. Tapi tebakan saya adalah karena pendekatan ini tidak fungsional, tidak berorientasi objek.
Manoj R
1
Tetapi konsep yang disampaikan dekat dengan pencocokan pola yang digunakan dalam pemrograman fungsional, yaitu $whostosaymenjadi tipe objek yang menentukan apa yang akan dieksekusi. Di atas dapat dimodifikasi untuk menerima parameter lain $whattosaysehingga tipe yang mendukungnya (mis. 'human') Dapat menggunakannya.
syockit