Desain dengan anggota statis

Meskipun Java sebagian besar berorientasi objek, itu bukan bahasa berorientasi objek murni . Salah satu alasan Java tidak murni berorientasi objek adalah karena tidak semua isinya adalah objek. Misalnya, Java memungkinkan Anda untuk mendeklarasikan variabel dari tipe primitif ( int, float, boolean, dll) yang tidak objek. Dan Java memiliki bidang dan metode statis, yang independen dan terpisah dari objek. Artikel ini memberikan saran tentang cara menggunakan bidang dan metode statis dalam program Java, sambil mempertahankan fokus berorientasi objek dalam desain Anda.

Masa pakai kelas di mesin virtual Java (JVM) memiliki banyak kesamaan dengan masa pakai objek. Seperti halnya sebuah objek dapat memiliki status, yang diwakili oleh nilai variabel instannya, sebuah kelas dapat memiliki status, yang diwakili oleh nilai variabel kelasnya. Sama seperti JVM menetapkan variabel contoh ke nilai awal default sebelum menjalankan kode inisialisasi, JVM menetapkan variabel kelas ke nilai awal default sebelum menjalankan kode inisialisasi. Dan seperti objek, kelas dapat dikumpulkan sampahnya jika tidak lagi direferensikan oleh aplikasi yang sedang berjalan.

Namun demikian, terdapat perbedaan yang signifikan antara kelas dan objek. Mungkin perbedaan yang paling penting adalah cara instance dan metode kelas dipanggil: metode instance (untuk sebagian besar) terikat secara dinamis, tetapi metode kelas terikat secara statis. (Dalam tiga kasus khusus, metode instance tidak terikat secara dinamis: pemanggilan metode instance privat, pemanggilan initmetode (konstruktor), dan pemanggilan dengan superkata kunci. Lihat Resource untuk informasi selengkapnya.)

Perbedaan lain antara kelas dan objek adalah tingkat penyembunyian data yang diberikan oleh tingkat akses pribadi. Jika variabel instance dinyatakan pribadi, hanya metode instance yang dapat mengaksesnya. Ini memungkinkan Anda memastikan integritas data instance dan membuat objek aman untuk thread. Program lainnya tidak dapat mengakses variabel instan tersebut secara langsung, tetapi harus melalui metode instan untuk memanipulasi variabel instan. Dalam upaya untuk membuat kelas berperilaku seperti objek yang dirancang dengan baik, Anda dapat membuat variabel kelas menjadi privat dan menentukan metode kelas yang memanipulasinya. Namun demikian, Anda tidak mendapatkan jaminan keamanan thread atau bahkan integritas data yang baik dengan cara ini, karena jenis kode tertentu memiliki hak istimewa yang memberi mereka akses langsung ke variabel kelas privat: metode instance,dan bahkan penginisialisasi variabel instan, dapat mengakses variabel kelas privat tersebut secara langsung.

Jadi bidang statis dan metode kelas, meskipun serupa dalam banyak hal dengan bidang contoh dan metode objek, memiliki perbedaan signifikan yang akan memengaruhi cara Anda menggunakannya dalam desain.

Memperlakukan kelas sebagai objek

Saat Anda mendesain program Java, Anda mungkin akan menghadapi banyak situasi di mana Anda merasa membutuhkan objek yang bertindak dalam beberapa cara seperti kelas. Anda mungkin, misalnya, menginginkan sebuah objek yang masa hidupnya sesuai dengan kelas. Atau Anda mungkin menginginkan objek yang, seperti kelas, membatasi dirinya sendiri ke satu contoh dalam ruang nama tertentu.

Dalam situasi desain seperti ini, mungkin tergoda untuk membuat kelas dan menggunakannya seperti objek untuk mendefinisikan variabel kelas, menjadikannya pribadi, dan mendefinisikan beberapa metode kelas publik yang memanipulasi variabel kelas. Seperti sebuah objek, kelas seperti itu memiliki status. Seperti objek yang dirancang dengan baik, variabel yang menentukan status bersifat privat, dan dunia luar hanya dapat memengaruhi status ini dengan menjalankan metode kelas.

Sayangnya, ada beberapa masalah dengan pendekatan "kelas-sebagai-objek" ini. Karena metode kelas terikat secara statis, kelas-sebagai-objek Anda tidak akan menikmati manfaat fleksibilitas dari polimorfisme dan upcasting. (Untuk definisi polimorfisme dan pengikatan dinamis, lihat artikel Teknik Desain, Komposisi versus Warisan.) Polimorfisme dimungkinkan, dan upcasting berguna, dengan pengikatan dinamis, tetapi metode kelas tidak terikat secara dinamis. Jika seseorang membuat subkelas kelas Anda sebagai objek, mereka tidak akan dapat mengganti metode kelas Anda dengan mendeklarasikan metode kelas dengan nama yang sama; mereka hanya akan bisa bersembunyimereka. Ketika salah satu dari metode kelas yang didefinisikan ulang ini dipanggil, JVM akan memilih implementasi metode yang akan dieksekusi bukan oleh kelas objek pada waktu proses, tetapi menurut jenis variabel pada waktu kompilasi.

Selain itu, keamanan thread dan integritas data yang dicapai dengan penerapan metode kelas yang cermat di kelas-sebagai-objek Anda seperti rumah yang dibangun dari jerami. Keamanan thread dan integritas data Anda akan dijamin selama semua orang menggunakan metode kelas untuk memanipulasi status yang disimpan dalam variabel kelas. Tetapi programmer yang ceroboh atau tidak tahu apa-apa dapat, dengan tambahan satu metode contoh yang mengakses variabel kelas privat Anda secara langsung, secara tidak sengaja terengah-engah dan menghancurkan keamanan thread dan integritas data Anda.

Untuk alasan ini, pedoman utama saya tentang variabel kelas dan metode kelas adalah:

Jangan perlakukan kelas seperti objek.

Dengan kata lain, jangan mendesain dengan bidang statis dan metode kelas seolah-olah mereka adalah bidang contoh dan metode objek.

Jika Anda menginginkan beberapa status dan perilaku yang masa hidupnya cocok dengan kelas, hindari menggunakan variabel kelas dan metode kelas untuk mensimulasikan objek. Sebagai gantinya, buat objek aktual dan gunakan variabel kelas untuk menampung referensi ke objek tersebut dan metode kelas untuk memberikan akses ke referensi objek. Jika Anda ingin memastikan bahwa hanya satu contoh dari beberapa keadaan dan perilaku yang ada dalam satu ruang nama, jangan mencoba merancang kelas yang mensimulasikan sebuah objek. Sebagai gantinya, buat singleton - objek yang dijamin hanya memiliki satu instance per ruang nama.

Jadi, apa gunanya anggota kelas?

Menurut pendapat saya, pola pikir terbaik untuk dikembangkan saat mendesain program Java adalah memikirkan objek, objek, objek. Fokus pada mendesain objek yang hebat, dan pikirkan kelas terutama sebagai cetak biru untuk objek - struktur tempat Anda menentukan variabel instan dan metode instans yang menyusun objek yang dirancang dengan baik. Selain itu, Anda dapat menganggap class menyediakan beberapa layanan khusus yang tidak dapat disediakan oleh objek, atau tidak dapat disediakan dengan elegan. Pikirkan kelas sebagai:

  • tempat yang tepat untuk mendefinisikan "metode utilitas" (metode yang mengambil masukan dan memberikan keluaran hanya melalui parameter yang diteruskan dan nilai kembalian)
  • cara untuk mengontrol akses ke objek dan data

Metode utilitas

Metode yang tidak memanipulasi atau menggunakan status objek atau kelas yang saya sebut "metode utilitas". Metode utilitas hanya mengembalikan beberapa nilai (atau nilai) yang dihitung hanya dari data yang diteruskan ke metode sebagai parameter. Anda harus membuat metode seperti itu statis dan menempatkannya di kelas yang paling dekat hubungannya dengan layanan yang disediakan metode.

Contoh metode utilitas adalah String copyValueOf(char[] data)metode kelas String. Metode ini menghasilkan keluarannya, nilai kembalian tipe String, hanya dari parameter masukannya, sebuah larik chars. Karena copyValueOf()tidak menggunakan atau memengaruhi status objek atau kelas apa pun, ini adalah metode utilitas. Dan, seperti semua metode utilitas seharusnya, copyValueOf()adalah metode kelas.

Jadi salah satu cara utama untuk menggunakan metode kelas adalah sebagai metode utilitas - metode yang mengembalikan keluaran yang dihitung hanya dari parameter masukan. Kegunaan lain dari metode kelas melibatkan variabel kelas.

Variabel kelas untuk menyembunyikan data

Salah satu prinsip dasar dalam pemrograman berorientasi objek adalah penyembunyian data - membatasi akses ke data untuk meminimalkan ketergantungan antara bagian-bagian program. Jika bagian data tertentu memiliki aksesibilitas terbatas, data tersebut dapat berubah tanpa merusak bagian program yang tidak dapat mengakses data tersebut.

Jika, misalnya, sebuah objek hanya diperlukan oleh instance dari kelas tertentu, referensi ke objek itu dapat disimpan dalam variabel kelas privat. Ini memberi semua instance dari kelas ini akses praktis ke objek itu - instance hanya menggunakannya secara langsung - tetapi tidak ada kode lain di mana pun dalam program yang bisa mendapatkannya. Dengan cara yang sama, Anda dapat menggunakan akses paket dan variabel kelas yang dilindungi untuk mengurangi visibilitas objek yang perlu dibagikan oleh semua anggota paket dan subkelas.

Variabel kelas publik adalah cerita yang berbeda. Jika variabel kelas publik belum final, itu adalah variabel global: konstruksi buruk itu adalah antitesis dari penyembunyian data. Tidak pernah ada alasan untuk variabel kelas publik, kecuali itu final.

Variabel kelas publik akhir, baik tipe primitif atau referensi objek, memiliki tujuan yang berguna. Variabel tipe atau tipe primitif Stringhanyalah konstanta, yang secara umum membantu membuat program lebih fleksibel (lebih mudah diubah). Kode yang menggunakan konstanta lebih mudah diubah karena Anda dapat mengubah nilai konstanta di satu tempat. Variabel kelas akhir publik dari tipe referensi memungkinkan Anda memberikan akses global ke objek yang dibutuhkan secara global. Sebagai contoh, System.in, System.out, dan System.erradalah variabel kelas akhir publik yang memberikan akses global untuk standar input output dan kesalahan sungai.

Jadi cara utama untuk melihat variabel kelas adalah sebagai mekanisme untuk membatasi aksesibilitas (artinya, menyembunyikan) variabel atau objek. Saat Anda menggabungkan metode kelas dengan variabel kelas, Anda dapat menerapkan kebijakan akses yang lebih rumit.

Menggunakan metode kelas dengan variabel kelas

Selain bertindak sebagai metode utilitas, metode kelas dapat digunakan untuk mengontrol akses ke objek yang disimpan dalam variabel kelas - khususnya, untuk mengontrol bagaimana objek dibuat atau dikelola. Dua contoh dari metode kelas semacam ini adalah metode setSecurityManager()dan getSecurityManager()kelas System. Manajer keamanan untuk aplikasi adalah objek yang, seperti input standar, output, dan aliran kesalahan, dibutuhkan di banyak tempat berbeda. Tidak seperti objek aliran I / O standar, bagaimanapun, referensi ke manajer keamanan tidak disimpan dalam variabel kelas akhir publik. Objek pengelola keamanan disimpan dalam variabel kelas privat, dan set dan metode get mengimplementasikan kebijakan akses khusus untuk objek tersebut.

Model keamanan Java menempatkan batasan khusus pada manajer keamanan. Sebelum Java 2 (sebelumnya dikenal sebagai JDK 1.2), aplikasi memulai hidupnya tanpa pengelola keamanan ( getSecurityManager()dikembalikan null). Panggilan pertama untuk setSecurityManager()mendirikan manajer keamanan, yang setelah itu tidak diizinkan untuk diubah. Setiap panggilan berikutnya ke setSecurityManager()akan menghasilkan pengecualian keamanan. Di Java 2, aplikasi selalu dimulai dengan manajer keamanan, tetapi mirip dengan versi sebelumnya, setSecurityManager()metode ini memungkinkan Anda untuk mengubah manajer keamanan paling banyak satu kali.

Manajer keamanan memberikan contoh yang baik tentang bagaimana metode kelas dapat digunakan bersama dengan variabel kelas privat untuk mengimplementasikan kebijakan akses khusus untuk objek yang dirujuk oleh variabel kelas. Selain metode utilitas, pikirkan metode kelas sebagai sarana untuk menetapkan kebijakan akses khusus untuk referensi objek dan data yang disimpan dalam variabel kelas.

Pedoman

Poin utama dari saran yang diberikan dalam artikel ini adalah:

Jangan perlakukan kelas seperti objek.

Jika Anda membutuhkan sebuah benda, buatlah sebuah benda. Batasi penggunaan variabel dan metode kelas Anda untuk menentukan metode utilitas dan menerapkan jenis kebijakan akses khusus untuk objek dan jenis primitif yang disimpan dalam variabel kelas. Meskipun bukan bahasa berorientasi objek murni, Java sebagian besar berorientasi objek, dan desain Anda harus mencerminkan itu. Pikirkan objek.

Bulan depan

Artikel Teknik Desain bulan depan akan menjadi yang terakhir dari kolom ini. Saya akan segera mulai menulis buku berdasarkan materi Teknik Desain, Java Fleksibel , dan akan menempatkan materi itu di situs web saya saat saya pergi. Jadi tolong ikuti proyek itu dan kirimkan saya umpan balik. Setelah istirahat satu atau dua bulan, saya akan kembali ke JavaWorld dan SunWorld dengan kolom baru yang berfokus pada Jini.

Permintaan partisipasi pembaca

Saya mendorong komentar, kritik, saran, api - semua jenis umpan balik - tentang materi yang disajikan di kolom ini. Jika Anda tidak setuju dengan sesuatu, atau ingin menambahkan sesuatu, beri tahu saya.

Anda dapat berpartisipasi dalam forum diskusi yang ditujukan untuk materi ini, memasukkan komentar melalui formulir di bagian bawah artikel, atau mengirim email kepada saya langsung menggunakan tautan yang tersedia di bio saya di bawah ini.

Bill Venners telah menulis perangkat lunak secara profesional selama 12 tahun. Berbasis di Silicon Valley, dia menyediakan layanan konsultasi dan pelatihan perangkat lunak dengan nama Artima Software Company. Selama bertahun-tahun ia telah mengembangkan perangkat lunak untuk elektronik konsumen, pendidikan, semikonduktor, dan industri asuransi jiwa. Dia telah memprogram dalam banyak bahasa di banyak platform: bahasa assembly di berbagai mikroprosesor, C di Unix, C ++ di Windows, Java di Web. Dia adalah penulis buku Inside the Java Virtual Machine, diterbitkan oleh McGraw-Hill.