Jumlah waktu yang signifikan, saya tidak bisa memikirkan alasan untuk memiliki objek, bukan kelas statis. Apakah objek memiliki manfaat lebih daripada yang saya kira? [Tutup]

9

Saya memahami konsep suatu objek, dan sebagai programmer Java saya merasakan paradigma OO datang secara alami kepada saya dalam praktiknya.

Namun baru-baru ini saya mendapati diri saya berpikir:

Tunggu sebentar, apa sebenarnya manfaat praktis menggunakan objek daripada menggunakan kelas statis (dengan enkapsulasi dan praktik OO yang tepat)?

Saya bisa memikirkan dua manfaat menggunakan objek (keduanya signifikan dan kuat):

  1. Polimorfisme: memungkinkan Anda untuk menukar fungsionalitas secara dinamis dan fleksibel selama runtime. Juga memungkinkan untuk menambahkan 'bagian' fungsionalitas baru dan alternatifnya ke sistem dengan mudah. Misalnya jika ada Carkelas yang dirancang untuk bekerja dengan Engineobjek, dan Anda ingin menambahkan Mesin baru ke sistem yang dapat digunakan oleh Mobil, Anda dapat membuat Enginesubkelas baru dan cukup mengirimkan objek kelas ini ke Carobjek, tanpa harus ubah apa saja tentang Car. Dan Anda dapat memutuskan untuk melakukannya selama runtime.

  2. Mampu 'menyampaikan fungsionalitas': Anda dapat melewatkan objek di sekitar sistem secara dinamis.

Tetapi apakah ada lebih banyak keuntungan pada objek dibandingkan kelas statis?

Seringkali ketika saya menambahkan 'bagian' baru ke sistem, saya melakukannya dengan membuat kelas baru dan membuat objek dari itu.

Tetapi baru-baru ini ketika saya berhenti dan memikirkannya, saya menyadari bahwa kelas statis akan melakukan hal yang sama dengan objek, di banyak tempat di mana saya biasanya menggunakan objek.

Misalnya, saya sedang berupaya menambahkan mekanisme simpan / muat-file ke aplikasi saya.

Dengan sebuah objek, baris kode panggilan akan terlihat seperti ini: Thing thing = fileLoader.load(file);

Dengan kelas statis, akan terlihat seperti ini: Thing thing = FileLoader.load(file);

Apa bedanya?

Cukup sering saya tidak bisa memikirkan alasan untuk membuat instance objek ketika kelas statis lama-polos akan bertindak sama. Tetapi dalam sistem OO, kelas statis cukup langka. Jadi saya pasti kehilangan sesuatu.

Apakah ada lebih banyak manfaat untuk objek selain dari dua yang saya daftarkan? Tolong jelaskan.

EDIT: Untuk memperjelas. Saya menemukan benda sangat berguna ketika bertukar fungsionalitas, atau meneruskan data. Misalnya saya menulis aplikasi yang membuat melodi. MelodyGeneratormemiliki beberapa subclass yang membuat melodi secara berbeda, dan objek dari kelas-kelas ini dapat dipertukarkan (pola Strategi).

Melodi juga objek, karena berguna untuk menyebarkannya. Begitu juga dengan Chords and Scales.

Tetapi bagaimana dengan bagian 'statis' dari sistem - yang tidak akan diedarkan? Misalnya - mekanisme 'simpan file'. Mengapa saya harus mengimplementasikannya dalam objek, dan bukan kelas statis?

Aviv Cohn
sumber
Jadi, alih-alih objek dengan bidang dan mungkin metode, tanpa objek, tanpa catatan, hanya seluruh nilai skalar yang diteruskan ke dan dikembalikan dari metode statis? Sunting: Contoh baru Anda menyarankan sebaliknya: Objek, hanya tanpa metode contoh? Kalau tidak, apa Thing?
Apa yang terjadi ketika Anda perlu menukar dengan yang Anda FileLoaderbaca dari soket? Atau tiruan untuk pengujian? Atau yang membuka file zip?
Benjamin Hodgson
1
@delnan Oke saya menemukan pertanyaan yang jawabannya akan membantu saya memahami: mengapa Anda menerapkan bagian 'statis' dari sistem sebagai objek? Seperti contoh dalam pertanyaan: mekanisme penyimpanan file. Apa yang saya dapat dari menerapkannya dalam suatu objek?
Aviv Cohn
1
Defaultnya adalah menggunakan objek non-statis. Hanya gunakan kelas statis jika Anda merasa itu benar-benar mengekspresikan niat Anda dengan lebih baik. System.Mathdi .NET adalah contoh dari sesuatu yang jauh lebih masuk akal sebagai kelas statis: Anda tidak akan perlu menukar atau mengejeknya dan tidak ada operasi yang secara logis dapat menjadi bagian dari instance. Saya benar-benar tidak berpikir contoh 'menabung' Anda sesuai dengan tagihan itu.
Benjamin Hodgson

Jawaban:

14

lol Anda terdengar seperti tim yang dulu pernah saya kerjakan;)

Java (dan mungkin C #) tentu mendukung gaya pemrograman itu. Dan saya bekerja dengan orang-orang yang insting pertamanya adalah, "Saya bisa menjadikannya metode statis!" Tetapi ada beberapa biaya halus yang mengejar Anda dari waktu ke waktu.

1) Java adalah bahasa yang Berorientasi Objek. Dan itu mendorong orang-orang fungsional kacang, tetapi benar-benar memegang cukup baik. Gagasan di balik OO adalah bundling fungsionalitas dengan keadaan untuk memiliki unit kecil data dan fungsionalitas yang mempertahankan semantiknya dengan menyembunyikan keadaan dan hanya memaparkan fungsi yang masuk akal dalam konteks itu.

Dengan pindah ke kelas dengan metode statis saja, Anda melanggar bagian "state" dari persamaan. Tetapi negara masih harus tinggal di suatu tempat. Jadi apa yang saya lihat dari waktu ke waktu adalah bahwa kelas dengan semua metode statis mulai memiliki daftar parameter yang semakin rumit, karena statusnya bergerak dari kelas dan masuk ke pemanggilan fungsi.

Setelah Anda membuat kelas dengan semua metode statis, jalankan dan hanya survei berapa banyak metode yang memiliki parameter tunggal yang umum. Ini adalah petunjuk bahwa parameter harus menjadi kelas yang mengandung fungsi-fungsi tersebut, atau parameter itu harus menjadi atribut dari instance.

2) Aturan untuk OO cukup dipahami. Setelah beberapa saat, Anda dapat melihat desain kelas dan melihat apakah itu memenuhi kriteria seperti SOLID. Dan setelah banyak pengujian unit praktik, Anda mengembangkan pemahaman yang baik tentang apa yang membuat kelas "berukuran tepat" dan "koheren". Tetapi tidak ada aturan yang baik untuk sebuah kelas dengan semua metode statis, dan tidak ada alasan nyata mengapa Anda tidak harus menggabungkan semua yang ada di sana. Kelas terbuka di editor Anda, jadi apa-apaan ini? Cukup tambahkan metode baru Anda di sana. Setelah beberapa saat, aplikasi Anda berubah menjadi sejumlah "Objek Dewa" yang bersaing, masing-masing berusaha untuk mendominasi dunia. Sekali lagi, refactoring mereka menjadi unit yang lebih kecil sangat subjektif dan sulit untuk mengatakan apakah Anda sudah benar.

3) Antarmuka adalah salah satu fitur paling kuat di Jawa. Warisan kelas telah terbukti bermasalah, tetapi pemrograman dengan antarmuka tetap menjadi salah satu trik bahasa yang paling kuat. (lagi ke C #) Semua kelas statis tidak dapat menempatkan diri mereka ke dalam model itu.

4) Ini membanting pintu pada teknik OO penting yang tidak dapat Anda manfaatkan. Jadi, Anda dapat bekerja selama bertahun-tahun hanya dengan palu di kotak peralatan Anda, tanpa menyadari betapa lebih mudahnya jika Anda memiliki obeng juga.

4.5) Ini menciptakan dependensi waktu kompilasi yang paling sulit, paling tidak bisa dipecahkan. Jadi, misalnya jika Anda memilikinya FileSystem.saveFile()maka tidak ada cara untuk mengubahnya, kecuali memalsukan JVM Anda saat run time. Yang berarti bahwa setiap kelas yang mereferensikan kelas fungsi statis Anda memiliki ketergantungan, waktu kompilasi yang sulit pada implementasi spesifik itu, yang membuat ekstensi hampir tidak mungkin, dan sangat menyulitkan pengujian. Anda dapat menguji kelas statis secara terpisah, tetapi menjadi sangat sulit untuk menguji kelas yang merujuk ke kelas itu secara terpisah.

5) Anda akan membuat rekan kerja Anda gila. Sebagian besar profesional yang bekerja dengan saya menganggap serius kode mereka, dan memperhatikan setidaknya beberapa tingkat prinsip desain. Mengesampingkan maksud inti dari suatu bahasa akan membuat mereka mencabut rambut mereka karena mereka akan terus-menerus memperbaiki kode.

Ketika saya dalam bahasa, saya selalu mencoba menggunakan bahasa dengan baik. Jadi, misalnya, ketika saya berada di Jawa, saya menggunakan desain OO yang bagus, karena dengan begitu saya benar-benar memanfaatkan bahasa untuk apa fungsinya. Ketika saya menggunakan Python, saya mencampur fungsi tingkat modul dengan kelas sesekali - saya hanya bisa menulis kelas dengan Python, tapi kemudian saya pikir saya tidak akan menggunakan bahasa untuk apa yang baik.

Taktik lain adalah menggunakan bahasa dengan buruk, dan mereka mengeluh tentang semua masalah yang disebabkannya. Tapi itu berlaku untuk hampir semua teknologi.

Fitur utama Java adalah mengelola kompleksitas dalam unit-unit kecil yang dapat diuji yang saling menggantung sehingga mudah dipahami. Java menekankan definisi antarmuka yang jelas terlepas dari implementasi - yang merupakan manfaat besar. Itu sebabnya (dan bahasa OO serupa lainnya) tetap digunakan secara luas. Untuk semua verbositas dan ritualisme, ketika saya selesai dengan aplikasi Java besar, saya selalu merasa ide-ide lebih bersih dipisahkan dalam kode daripada proyek saya dalam bahasa yang lebih dinamis.

Tapi itu sulit. Saya telah melihat orang-orang mendapatkan bug "semua statis", dan agak sulit untuk mengeluarkannya. Tetapi saya telah melihat mereka memiliki perasaan lega yang besar ketika mereka mengatasinya.

rampok
sumber
Anda berbicara terutama tentang menjaga hal-hal kecil dan modular, dan menjaga keadaan dan fungsi bersama. Tidak ada yang menghentikan saya melakukan ini dengan kelas statis. Mereka dapat memiliki negara. Dan Anda dapat merangkum mereka dengan getter-setter. Dan Anda dapat membagi sistem ke kelas-kelas kecil yang merangkum fungsionalitas dan status. Semua ini berlaku untuk kelas dan objek. Dan inilah dilema saya: katakan saya menambahkan fungsionalitas baru ke aplikasi saya. Jelas itu akan pergi di kelas yang terpisah untuk mematuhi SRP. Tapi mengapa saya harus instantiate kelas ini? Ini yang tidak saya mengerti.
Aviv Cohn
Maksud saya: terkadang jelas mengapa saya menginginkan benda. Saya akan menggunakan contoh dari edit ke pertanyaan saya: Saya punya aplikasi yang membentuk melodi. Ada Timbangan yang berbeda yang bisa saya pasang di MelodyGenerators untuk menghasilkan melodi yang berbeda. Dan Melodies adalah objek, jadi saya bisa meletakkannya di tumpukan dan kembali memainkan yang lama, dll. Dalam kasus seperti ini, jelas bagi saya mengapa saya harus menggunakan objek. Yang tidak saya mengerti adalah mengapa saya harus menggunakan objek untuk mewakili bagian 'statis' dari sistem: misalnya mekanisme penyimpanan file. Mengapa ini tidak hanya menjadi kelas statis?
Aviv Cohn
Kelas dengan metode statis harus mengeksternalisasi keadaannya. Yang, kadang-kadang, adalah teknik anjak piutang yang sangat penting. Tetapi sebagian besar waktu Anda ingin merangkum keadaan. Contoh nyata: tahun lalu seorang rekan kerja menulis "pemilih tanggal" dalam Javascript. Dan itu adalah mimpi buruk. Para pelanggan mengeluh tentang hal itu terus-menerus. Jadi saya refactored menjadi objek "kalender", dan tiba-tiba saya instantiate beberapa dari mereka, menempatkan mereka berdampingan, melompat antara bulan dan tahun, dll. Itu sangat kaya sehingga kami benar-benar harus mematikan fitur. Instansiasi memberi Anda skala itu.
Rob
3
"Gagasan di balik OO adalah menggabungkan fungsi dengan negara untuk memiliki unit kecil data dan fungsionalitas yang mempertahankan semantik mereka dengan menyembunyikan negara dan hanya memperlihatkan fungsi yang masuk akal dalam konteks itu." Ini pada dasarnya salah. OO tidak menyiratkan keadaan yang bisa berubah dan abstraksi tidak eksklusif untuk OO. Ada dua cara untuk mencapai abstraksi dan objek hanya salah satunya (yang lainnya adalah tipe data abstrak).
Doval
1
@Doval Saya tidak mengerti mengapa setiap diskusi tentang OO harus berubah menjadi diskusi tentang pemrograman fungsional.
Rob
6

Kamu bertanya:

Tetapi apakah ada lebih banyak keuntungan pada objek dibandingkan kelas statis?

Sebelum pertanyaan ini, Anda mencantumkan Polimorfisme dan diedarkan sebagai dua manfaat menggunakan Objek. Saya ingin mengatakan bahwa itu adalah fitur dari paradigma OO. Enkapsulasi adalah fitur lain dari paradigma OO.

Namun, itu bukan manfaatnya. Manfaatnya adalah:

  1. Abstraksi yang lebih baik
  2. Pemeliharaan yang lebih baik
  3. Testabilitas yang lebih baik

Kamu berkata:

Tetapi baru-baru ini ketika saya berhenti dan memikirkannya, saya menyadari bahwa kelas statis akan melakukan hal yang sama dengan objek, di banyak tempat di mana saya biasanya menggunakan objek.

Saya pikir Anda memiliki poin yang valid di sana. Pada intinya, pemrograman tidak lain adalah transformasi data dan penciptaan efek samping berdasarkan data. Terkadang mengubah data membutuhkan data tambahan. Di lain waktu, tidak.

Ketika Anda berurusan dengan kategori pertama dari transformasi, data tambahan harus dimasukkan sebagai input atau disimpan di suatu tempat. Objek adalah pendekatan yang lebih baik daripada kelas statis untuk transformasi semacam itu. Objek dapat menyimpan data tambahan dan menggunakannya pada waktu yang tepat.

Untuk kategori kedua dari transformasi, kelas statis sama baiknya dengan Obyek, jika tidak lebih baik. Fungsi matematika adalah contoh klasik dari kategori ini. Sebagian besar fungsi pustaka C standar termasuk dalam kategori ini juga.

Kamu bertanya:

Dengan sebuah objek, baris kode panggilan akan terlihat seperti ini: Thing thing = fileLoader.load(file);

Dengan kelas statis, akan terlihat seperti ini: Thing thing = FileLoader.load(file);

Apa bedanya?

Jika FileLoadertidak, pernah , perlu menyimpan data apa pun, saya akan pergi dengan pendekatan kedua. Jika ada sedikit peluang bahwa itu akan membutuhkan data tambahan untuk melakukan operasi, pendekatan pertama adalah taruhan yang lebih aman.

Kamu bertanya:

Apakah ada lebih banyak manfaat untuk objek selain dari dua yang saya daftarkan? Tolong jelaskan.

Saya membuat daftar manfaat (keuntungan) menggunakan paradigma OO. Saya harap mereka cukup jelas. Jika tidak, saya akan senang menjelaskannya.

Kamu bertanya:

Tetapi bagaimana dengan bagian 'statis' dari sistem - yang tidak akan diedarkan? Misalnya - mekanisme 'simpan file'. Mengapa saya harus mengimplementasikannya dalam objek, dan bukan kelas statis?

Ini adalah contoh di mana kelas statis tidak akan dilakukan. Ada banyak cara untuk menyimpan data aplikasi Anda ke file:

  1. Simpan dalam file CSV.
  2. Simpan dalam file XML.
  3. Simpan dalam file json.
  4. Simpan sebagai file biner, dengan dump data langsung.
  5. Simpan langsung ke beberapa tabel dalam database.

Satu-satunya cara untuk menyediakan opsi tersebut adalah dengan membuat Antarmuka dan membuat Objek yang mengimplementasikan antarmuka.

Kesimpulannya

Gunakan pendekatan yang tepat untuk masalah yang dihadapi. Lebih baik tidak beragama tentang satu pendekatan vs yang lain.

R Sahu
sumber
Juga, jika banyak jenis objek yang berbeda (kelas) perlu diselamatkan (misalnya Melody, Chord, Improvisations, SoundSampledan lain-lain), maka akan ekonomis untuk menyederhanakan pelaksanaan melalui abstraksi.
rwong
5

Itu tergantung pada bahasa dan konteksnya, kadang-kadang. Misalnya, PHPskrip yang digunakan untuk melayani permintaan selalu memiliki satu permintaan untuk layanan dan satu respons untuk dihasilkan sepanjang masa pakai skrip, sehingga metode statis untuk bertindak atas permintaan dan menghasilkan respons mungkin tepat. Tetapi dalam server yang ditulis Node.js, mungkin ada banyak permintaan dan tanggapan yang berbeda pada saat yang bersamaan. Jadi pertanyaan pertama adalah - apakah Anda yakin bahwa kelas statis benar-benar sesuai dengan objek tunggal?

Kedua, bahkan jika Anda memiliki lajang, menggunakan objek memungkinkan Anda untuk mengambil keuntungan dari polimorfisme menggunakan teknik seperti Dependency_injection dan Factory_method_pattern . Ini sering digunakan dalam berbagai pola Inversion_of_control , dan berguna untuk membuat objek tiruan untuk pengujian, pencatatan, dll.

Anda menyebutkan keuntungan di atas, jadi di sini adalah salah satu yang tidak Anda dapatkan: warisan. Banyak bahasa tidak memiliki kemampuan untuk menimpa metode statis dengan cara yang sama seperti metode instance dapat ditimpa. Secara umum, jauh lebih sulit untuk mewarisi dan mengganti metode statis.

Gregory Magarshak
sumber
Terimakasih telah menjawab. Menurut pendapat Anda: ketika membuat bagian 'statis' dari sistem, sesuatu yang tidak akan 'diedarkan' - misalnya bagian dari sistem yang memutar suara, atau bagian dari sistem yang menyimpan data ke file: haruskah saya mengimplementasikannya di objek atau di kelas statis?
Aviv Cohn
3

Selain posting Rob Y


Selama fungsionalitas Anda load(File file)dapat dipisahkan dengan jelas dari semua fungsi lain yang Anda gunakan, boleh saja menggunakan metode / kelas statis. Anda mengeksternalisasi keadaan (yang bukan hal buruk) dan Anda juga tidak mendapatkan redundansi seperti yang Anda dapat misalnya menerapkan sebagian atau menjelajah fungsi Anda sehingga Anda tidak perlu mengulangi sendiri. (yang sebenarnya sama atau mirip dengan menggunakan factorypola)

Namun, begitu dua fungsi ini mulai memiliki penggunaan umum, Anda ingin dapat mengelompokkannya. Bayangkan Anda tidak hanya memiliki loadfungsi tetapi juga hasValidSyntaxfungsi. Apa yang akan kamu lakukan?

     if (FileLoader.hasValidSyntax(myfile))
          Thing thing = FileLoader.load(myfile);
     else
          println "oh noes!"

Lihat dua referensi di myfilesini? Anda mulai mengulangi diri Anda sendiri karena kondisi eksternal Anda harus dilewati untuk setiap panggilan. Rob Y telah menjelaskan bagaimana Anda menginternalisasi negara (di sini file) sehingga Anda dapat melakukannya seperti ini:

     FileLoader myfileLoader = new FileLoader(myfile)
     if (myfileLoader.hasValidSyntax())
          Thing thing = myfileLoader.load();
     else
          println "oh noes!"
valenterri
sumber
Harus melewati objek yang sama dua kali adalah gejala yang dangkal; masalah sebenarnya yang mungkin diindikasikan adalah bahwa beberapa pekerjaan dilakukan secara berlebihan - file mungkin harus dibuka dua kali, diurai dua kali, dan ditutup dua kali, jika hasValidSyntax()dan load()tidak diizinkan untuk menggunakan kembali keadaan (hasil dari file yang diurai sebagian).
rwong
2

Masalah utama ketika menggunakan kelas statis adalah mereka memaksa Anda untuk menyembunyikan dependensi Anda, dan memaksa Anda untuk bergantung pada implementasi. Dalam tanda tangan konstruktor berikut, apa dependensi Anda:

public Person(String name)

Nah, kalau dilihat dari tanda tangan, seseorang hanya perlu nama, kan? Ya, tidak jika implementasinya adalah:

public Person(String name) {
    ResultSet rs = DBConnection.getPersonFilePathByName(name);
    File f = FileLoader.load(rs.getPath());
    PersonData.setDataFile(f);
    this.name = name;
    this.age = PersonData.getAge();
}

Jadi seseorang tidak hanya dipakai. Kami benar-benar menarik data dari database, yang memberi kami jalur ke file, yang kemudian harus diuraikan, dan kemudian data nyata yang kami inginkan harus dihapus. Contoh ini jelas di atas, tetapi membuktikan intinya. Tapi tunggu, masih ada banyak lagi! Saya menulis tes berikut:

public void testPersonConstructor() {
    Person p = new Person("Milhouse van Houten");
    assertEqual(10, p.age);
}

Ini harus berlalu, kan? Maksudku, kita merangkum semua hal lainnya, kan? Yah, sebenarnya itu meledak dengan pengecualian. Mengapa? Oh, ya, dependensi tersembunyi yang tidak kita ketahui memiliki keadaan global. The DBConnectionkebutuhan diinisialisasi dan terhubung. The FileLoaderkebutuhan diinisialisasi dengan FileFormatobjek (seperti XMLFileFormatatau CSVFileFormat). Belum pernah dengar itu? Nah, itu intinya. Kode Anda (dan kompiler Anda) tidak dapat memberi tahu Anda bahwa Anda memerlukan hal-hal ini karena panggilan statis menyembunyikan dependensi tersebut. Apakah saya mengatakan tes? Maksud saya, pengembang junior yang baru saja mengirimkan sesuatu seperti ini di rilis terbaru Anda. Lagi pula, kompilasi = berfungsi, kan?

Selain itu, katakan Anda menggunakan sistem yang tidak memiliki instance MySQL yang sedang berjalan. Atau, katakan Anda menggunakan sistem Windows tetapi DBConnectionkelas Anda hanya keluar ke server MySQL Anda pada kotak Linux (dengan jalur Linux). Atau, katakan Anda berada di sistem di mana jalur yang dikembalikan oleh DBConnectiontidak membaca / menulis untuk Anda. Itu berarti bahwa mencoba menjalankan atau menguji sistem ini di bawah salah satu kondisi ini akan gagal, bukan karena kesalahan kode, tetapi karena kesalahan desain yang membatasi fleksibilitas kode dan mengikat Anda ke suatu implementasi.

Sekarang, katakanlah, kami ingin mencatat setiap panggilan ke database untuk satu Personcontoh spesifik , yang melewati jalur tertentu yang merepotkan. Kita dapat memasukkan logging ke dalam DBConnection, tetapi ini akan mencatat semuanya , meletakkan banyak kekacauan dan membuatnya sulit untuk membedakan jalur kode tertentu yang ingin kita lacak. Namun, jika kita menggunakan injeksi ketergantungan dengan sebuah DBConnectioninstance, kita bisa mengimplementasikan antarmuka dalam dekorator (atau memperluas kelas, karena kita memiliki kedua opsi yang tersedia dengan objek). Dengan kelas statis, kami tidak dapat menyuntikkan dependensi, kami tidak dapat mengimplementasikan antarmuka, kami tidak dapat membungkusnya dalam dekorator, dan kami tidak dapat memperluas kelas. Kami hanya dapat menyebutnya secara langsung, di suatu tempat tersembunyi jauh di dalam kode kami. Jadi kita dipaksa untuk memiliki ketergantungan tersembunyi pada suatu implementasi.

Apakah ini selalu buruk? Tidak harus, tetapi mungkin lebih baik membalikkan sudut pandang Anda dan berkata, "Apakah ada alasan bagus mengapa ini tidak menjadi contoh?" daripada "Apakah ada alasan yang baik ini harus menjadi contoh?" Jika Anda benar-benar dapat mengatakan bahwa kode Anda tidak akan goyah (dan tidak memiliki kewarganegaraan) seperti Math.abs(), baik dalam implementasinya maupun cara penggunaannya, maka Anda dapat mempertimbangkan untuk membuatnya statis. Namun, memiliki instance atas kelas statis, memberi Anda dunia fleksibilitas yang tidak selalu mudah untuk ditangkap kembali setelah fakta. Ini juga dapat memberi Anda lebih banyak kejelasan tentang sifat sebenarnya dari dependensi kode Anda.

cbojar
sumber
Ketergantungan tersembunyi adalah hal yang sangat bagus. Saya hampir lupa idiom saya bahwa "Kualitas kode harus dinilai dari bagaimana itu digunakan, bukan bagaimana itu diterapkan."
Euforia
Tapi dependensi tersembunyi juga bisa ada di kelas non-statis? Jadi saya tidak melihat mengapa ini akan menjadi kelemahan dari kelas statis tetapi bukan dari kelas non-statis.
valenterri
@valenterry Ya, kita juga bisa menyembunyikan dependensi non-statis, tetapi titik kuncinya adalah menyembunyikan dependensi non-statis adalah sebuah pilihan . Saya dapat newmengumpulkan banyak objek di konstruktor (yang umumnya tidak disarankan), tetapi saya juga dapat menyuntikkannya. Dengan kelas statis, tidak ada cara untuk menyuntikkannya (tidak mudah di Jawa, dan itu akan menjadi diskusi lain untuk bahasa yang memungkinkan itu), jadi tidak ada pilihan. Itu sebabnya saya menyoroti gagasan dipaksa menjadi sangat tergantung pada jawaban saya.
cbojar
Tapi Anda bisa menyuntikkannya setiap kali Anda memanggil metode dengan memberikannya sebagai argumen. Jadi Anda tidak dipaksa untuk menyembunyikannya tetapi dipaksa untuk membuatnya eksplisit sehingga semua orang melihat "aha, metode itu tergantung pada argumen ini" daripada "aha, metode itu tergantung pada argumen (bagian dari) ini dan beberapa keadaan interal tersembunyi yang saya tidak tahu".
valenterri
Di Jawa, sejauh yang saya tahu, Anda tidak dapat menyediakan kelas statis sebagai parameter tanpa melalui seluruh omong kosong refleksi. (Saya mencoba segala cara yang dapat saya pikirkan. Jika Anda memiliki cara, saya ingin melihatnya.) Dan jika Anda memang memilih untuk melakukan itu, Anda pada dasarnya menumbangkan sistem tipe bawaan (parameternya adalah Class, maka kami memastikan itu adalah kelas yang tepat) atau Anda mengetik bebek (kami memastikan itu menanggapi metode yang tepat). Jika Anda ingin melakukan yang terakhir, maka Anda harus mengevaluasi kembali pilihan bahasa Anda. Jika Anda ingin melakukan yang pertama, instans baik-baik saja dan dibangun.
cbojar
1

Hanya dua sen saya.

Untuk pertanyaan Anda:

Tetapi bagaimana dengan bagian 'statis' dari sistem - yang tidak akan diedarkan? Misalnya - mekanisme 'simpan file'. Mengapa saya harus mengimplementasikannya dalam objek, dan bukan kelas statis?

Anda dapat bertanya pada diri sendiri apakah mekanisme bagian dari sistem yang memutar suara, atau bagian dari sistem yang menyimpan data ke file AKAN MENGUBAH . Jika jawaban Anda adalah ya, itu menunjukkan bahwa Anda harus mengabstraksi mereka menggunakan abstract class/ interface. Anda mungkin bertanya, bagaimana saya bisa mengetahui hal-hal di masa depan? Jelas, kita tidak bisa. Jadi, jika masalahnya stateless, Anda dapat menggunakan 'kelas statis' seperti java.lang.Math, jika tidak, gunakan pendekatan berorientasi objek.

pengguna3663635
sumber
Ada saran dari mulut ke mulut: Tiga serangan dan Anda refactor , yang menunjukkan bahwa seseorang dapat menunda sampai perubahan benar-benar diperlukan. Yang saya maksud dengan "perubahan" adalah: lebih dari satu jenis objek perlu diselamatkan; atau perlu menyimpan lebih dari satu format file (tipe penyimpanan); atau peningkatan drastis dalam kompleksitas data yang disimpan. Tentu saja jika seseorang cukup yakin bahwa perubahan itu akan terjadi segera, seseorang dapat memasukkan desain yang lebih fleksibel di muka.
rwong