Saya mencari cara untuk lulus metode dengan referensi. Saya mengerti bahwa Java tidak lulus metode sebagai parameter, namun, saya ingin mendapatkan alternatif.
Saya telah diberitahu bahwa antarmuka adalah alternatif untuk melewati metode sebagai parameter, tetapi saya tidak mengerti bagaimana antarmuka dapat bertindak sebagai metode dengan referensi. Jika saya mengerti benar suatu antarmuka hanyalah seperangkat metode abstrak yang tidak didefinisikan. Saya tidak ingin mengirim antarmuka yang perlu didefinisikan setiap saat karena beberapa metode berbeda dapat memanggil metode yang sama dengan parameter yang sama.
Apa yang ingin saya capai adalah sesuatu yang mirip dengan ini:
public void setAllComponents(Component[] myComponentArray, Method myMethod) {
for (Component leaf : myComponentArray) {
if (leaf instanceof Container) { //recursive call if Container
Container node = (Container) leaf;
setAllComponents(node.getComponents(), myMethod);
} //end if node
myMethod(leaf);
} //end looping through components
}
dipanggil seperti:
setAllComponents(this.getComponents(), changeColor());
setAllComponents(this.getComponents(), changeSize());
Jawaban:
Sunting : pada Java 8, ekspresi lambda adalah solusi yang bagus seperti yang ditunjukkan oleh jawaban lain . Jawaban di bawah ini ditulis untuk Java 7 dan sebelumnya ...
Lihatlah pola perintah .
Sunting: seperti yang ditunjukkan Pete Kirkham , ada cara lain untuk melakukan ini menggunakan Pengunjung . Pendekatan pengunjung sedikit lebih terlibat - simpul Anda semua harus sadar pengunjung dengan suatu
acceptVisitor()
metode - tetapi jika Anda perlu menelusuri grafik objek yang lebih kompleks maka perlu diperiksa.sumber
Di Java 8, Anda sekarang dapat melewati metode lebih mudah menggunakan Ekspresi Lambda dan Referensi Metode. Pertama, beberapa latar belakang: antarmuka fungsional adalah antarmuka yang memiliki satu dan hanya satu metode abstrak, meskipun dapat berisi sejumlah metode default (baru di Java 8) dan metode statis. Ekspresi lambda dapat dengan cepat mengimplementasikan metode abstrak, tanpa semua sintaks yang tidak perlu diperlukan jika Anda tidak menggunakan ekspresi lambda.
Tanpa ekspresi lambda:
Dengan ekspresi lambda:
Berikut adalah kutipan dari tutorial Java tentang Ekspresi Lambda :
Inilah cara Anda dapat "meneruskan metode" menggunakan ekspresi lambda:
Kelas
C
dapat dipersingkat bahkan sedikit lebih jauh dengan menggunakan referensi metode seperti:sumber
::
operator), tidak masalah apa A.a.changeThing(component)
dapat diubah ke pernyataan atau blok kode apa pun yang Anda inginkan, asalkan mengembalikan batal.Gunakan
java.lang.reflect.Method
objek dan panggilinvoke
sumber
Karena Java 8 ada
Function<T, R>
antarmuka ( docs ), yang memiliki metodeAnda dapat menggunakannya untuk meneruskan fungsi sebagai parameter ke fungsi lainnya. T adalah tipe input dari fungsi, R adalah tipe kembali.
Dalam contoh Anda, Anda harus melewati fungsi yang mengambil
Component
tipe sebagai input dan tidak mengembalikan apa pun -Void
. Dalam halFunction<T, R>
ini bukan pilihan terbaik, karena tidak ada autoboxing tipe Void. Antarmuka yang Anda cari disebutConsumer<T>
( docs ) dengan metodeAkan terlihat seperti ini:
Dan Anda akan menyebutnya menggunakan referensi metode:
Dengan asumsi bahwa Anda telah mendefinisikan metode changeColor () dan changeSize () di kelas yang sama.
Jika metode Anda menerima lebih dari satu parameter, Anda dapat menggunakan
BiFunction<T, U, R>
- T dan U sebagai tipe parameter input dan R sebagai tipe pengembalian. Ada jugaBiConsumer<T, U>
(dua argumen, tidak ada tipe pengembalian). Sayangnya untuk 3 dan lebih banyak parameter input, Anda harus membuat antarmuka sendiri. Sebagai contoh:sumber
Pertama tentukan Antarmuka dengan metode yang ingin Anda lewati sebagai parameter
Menerapkan kelas dengan metode ini
// Ajukan seperti itu
Ini memungkinkan Anda untuk melewatkan cmd sebagai parameter dan memanggil pemanggilan metode yang didefinisikan dalam antarmuka
sumber
Meskipun ini belum berlaku untuk Java 7 dan di bawah, saya percaya bahwa kita harus melihat ke masa depan dan setidaknya mengenali perubahan yang akan terjadi dalam versi baru seperti Java 8.
Yaitu, versi baru ini membawa lambdas dan referensi metode ke Jawa (bersama dengan API baru , yang merupakan solusi lain yang valid untuk masalah ini. Meskipun mereka masih memerlukan antarmuka, tidak ada objek baru yang dibuat, dan file class tambahan tidak perlu mencemari direktori keluaran karena perbedaan penanganan oleh JVM.
Kedua rasa (lambda dan referensi metode) memerlukan antarmuka yang tersedia dengan metode tunggal yang tanda tangannya digunakan:
Nama metode tidak akan menjadi masalah mulai saat ini. Di mana lambda diterima, referensi metode juga. Misalnya, untuk menggunakan tanda tangan kami di sini:
Ini hanya permohonan antarmuka yang sederhana, hingga lambda 1 dilewati:
Ini akan menampilkan:
Referensi metode serupa. Diberikan:
dan utama:
hasilnya akan
real static method
. Referensi metode dapat berupa statis, instan, non-statis dengan instance acak, dan bahkan konstruktor . Untuk sesuatu yang mirip dengan konstruktorClassName::new
akan digunakan.1 Ini tidak dianggap lambda oleh beberapa orang, karena memiliki efek samping. Namun, hal itu menggambarkan penggunaan seseorang dengan cara yang lebih mudah divisualisasikan.
sumber
Terakhir kali saya memeriksa, Java tidak dapat melakukan apa yang Anda inginkan secara asli; Anda harus menggunakan 'work-arounds' untuk mengatasi keterbatasan tersebut. Sejauh yang saya lihat, antarmuka ADALAH alternatif, tetapi bukan alternatif yang baik. Mungkin siapa pun yang memberi tahu Anda itu artinya seperti ini:
Yang kemudian akan Anda ajukan:
sumber
Jika Anda tidak membutuhkan metode ini untuk mengembalikan sesuatu, Anda bisa membuatnya mengembalikan objek Runnable.
Kemudian gunakan seperti:
sumber
Saya tidak menemukan contoh yang cukup eksplisit bagi saya tentang cara menggunakan
java.util.function.Function
metode sederhana sebagai fungsi parameter. Ini adalah contoh sederhana:Pada dasarnya Anda memiliki
Foo
objek dengan konstruktor default. Amethod
yang akan dipanggil sebagai parameter dariparametrisedMethod
yang bertipeFunction<String, Foo>
.Function<String, Foo>
berarti bahwa fungsi tersebut mengambilString
parameter sebagai dan mengembalikan aFoo
.Foo::Method
bersesuaian dengan lambda sepertix -> Foo.method(x);
parametrisedMethod(Foo::method)
dapat dilihat sebagaix -> parametrisedMethod(Foo.method(x))
.apply("from a method")
dasarnya harus dilakukanparametrisedMethod(Foo.method("from a method"))
Yang kemudian akan kembali di output:
Contohnya harus berjalan apa adanya, Anda kemudian dapat mencoba hal-hal yang lebih rumit dari jawaban di atas dengan kelas dan antarmuka yang berbeda.
sumber
Java memang memiliki mekanisme untuk menyampaikan nama dan menyebutnya. Itu adalah bagian dari mekanisme refleksi. Fungsi Anda harus mengambil parameter tambahan dari Metode kelas.
sumber
Saya bukan ahli java tapi saya memecahkan masalah Anda seperti ini:
Saya mendefinisikan parameter di Antarmuka khusus saya
Akhirnya, saya menerapkan metode getSearchText sambil memanggil metode inisialisasi .
sumber
Gunakan pola Pengamat (kadang-kadang juga disebut pola Pendengar):
new ComponentDelegate()...
mendeklarasikan jenis anonim yang mengimplementasikan antarmuka.sumber
Ini adalah contoh dasarnya:
Keluaran:
sumber
Saya tidak menemukan solusi apa pun di sini yang menunjukkan cara melewatkan metode dengan parameter terikat padanya sebagai parameter metode. Di bawah ini adalah contoh bagaimana Anda dapat melewati metode dengan nilai parameter yang sudah terikat padanya.
Contoh lain menunjukkan cara melewatkan metode yang sebenarnya mengembalikan sesuatu
sumber
Contoh solusi dengan refleksi, metode yang lulus harus bersifat publik
sumber
Saya menghargai jawaban di atas tetapi saya dapat mencapai perilaku yang sama menggunakan metode di bawah ini; sebuah ide yang dipinjam dari panggilan balik Javascript. Saya terbuka untuk koreksi meskipun sejauh ini sangat baik (dalam produksi).
Idenya adalah untuk menggunakan tipe pengembalian fungsi dalam tanda tangan, yang berarti bahwa hasil harus statis.
Di bawah ini adalah fungsi yang menjalankan proses dengan batas waktu.
sumber