Apa keuntungan menggunakan kelas abstrak alih-alih suatu sifat (terlepas dari kinerja)? Sepertinya kelas abstrak dapat digantikan oleh ciri-ciri dalam banyak kasus.
371
Saya dapat memikirkan dua perbedaan
Ada bagian dalam Pemrograman dalam Scala yang disebut "To trait, or not to trait?" yang membahas pertanyaan ini. Karena edisi pertama tersedia online, saya harap tidak masalah mengutip semuanya di sini. (Setiap programmer Scala yang serius harus membeli buku itu):
Seperti @Mushtaq Ahmed sebutkan, suatu sifat tidak dapat memiliki parameter apa pun yang diteruskan ke konstruktor utama suatu kelas.
Perbedaan lain adalah perawatan
super
.Lihat sisa Bab 12 untuk lebih jelasnya.
Edit 1 (2013):
Ada perbedaan kecil dalam perilaku kelas abstrak dibandingkan dengan sifat. Salah satu aturan linierisasi adalah bahwa ia mempertahankan hierarki warisan kelas-kelas, yang cenderung mendorong kelas-kelas abstrak belakangan dalam rantai sementara sifat-sifat dapat dengan senang hati dicampurkan. Dalam keadaan tertentu, sebenarnya lebih disukai berada pada posisi terakhir dari linierisasi kelas. , jadi kelas abstrak bisa digunakan untuk itu. Lihat membatasi linierisasi kelas (urutan mixin) di Scala .
Edit 2 (2018):
Pada Scala 2.12, perilaku kompatibilitas biner sifat telah berubah. Sebelum 2.12, menambahkan atau menghapus anggota ke sifat diperlukan kompilasi ulang semua kelas yang mewarisi sifat itu, bahkan jika kelas tidak berubah. Ini karena cara pengkodean dalam JVM.
Pada Scala 2.12, ciri mengkompilasi ke antarmuka Java , sehingga persyaratan telah sedikit santai. Jika sifat melakukan salah satu dari yang berikut, subclassnya masih memerlukan kompilasi ulang:
Tetapi jika sifat itu tidak, Anda sekarang dapat memperbaruinya tanpa merusak kompatibilitas biner.
sumber
If outside clients will only call into the behavior, instead of inheriting from it, then using a trait is fine
- Bisakah seseorang menjelaskan apa bedanya di sini?extends
vswith
?extends
danwith
. Ini murni sintaksis. Jika Anda mewarisi dari banyak templat, yang pertama didapatextend
, semua yang lain dapatkanwith
, itu saja. Pikirkanwith
sebagai koma:class Foo extends Bar, Baz, Qux
.Untuk apa pun nilainya, Pemrograman Odersky et al di Scala merekomendasikan bahwa, ketika Anda ragu, Anda menggunakan sifat-sifat. Anda selalu dapat mengubahnya menjadi kelas abstrak nanti jika diperlukan.
sumber
Selain fakta bahwa Anda tidak dapat secara langsung memperluas beberapa kelas abstrak, tetapi Anda dapat menggabungkan beberapa sifat ke dalam kelas, perlu disebutkan bahwa sifat dapat ditumpuk, karena panggilan super dalam suatu sifat terikat secara dinamis (merujuk pada suatu kelas atau sifat yang dicampur sebelum saat ini).
Dari jawaban Thomas dalam Perbedaan antara Kelas Abstrak dan Sifat :
sumber
Ketika memperluas kelas abstrak, ini menunjukkan bahwa subclass adalah sejenis. Ini tidak selalu terjadi ketika menggunakan ciri-ciri, saya pikir.
sumber
Dalam Pemrograman Scala , penulis mengatakan bahwa kelas abstrak membuat hubungan objek "is-a" klasik berorientasi sedangkan sifat adalah scala-cara komposisi.
sumber
Kelas abstrak dapat berisi perilaku - Mereka dapat parameter dengan konstruktor args (yang tidak dapat ciri) dan mewakili entitas kerja. Alih-alih sifat hanya mewakili satu fitur, antarmuka dari satu fungsi.
sumber
trait Enumerable
dengan banyak fungsi pembantu, saya tidak akan menyebutnya perilaku tetapi hanya fungsionalitas yang terhubung dengan satu fitur.sumber