Apakah ada cara untuk membuat kelas abstrak dalam Bahasa Swift, atau apakah ini keterbatasan seperti Objective-C? Saya ingin membuat kelas abstrak yang sebanding dengan apa yang didefinisikan Java sebagai kelas abstrak.
140
Apakah ada cara untuk membuat kelas abstrak dalam Bahasa Swift, atau apakah ini keterbatasan seperti Objective-C? Saya ingin membuat kelas abstrak yang sebanding dengan apa yang didefinisikan Java sebagai kelas abstrak.
Jawaban:
Tidak ada kelas abstrak di Swift (seperti Objective-C). Taruhan terbaik Anda adalah menggunakan Protokol , yang seperti Java Interface.
Dengan Swift 2.0, Anda kemudian dapat menambahkan implementasi metode dan implementasi properti yang dihitung menggunakan ekstensi protokol. Satu-satunya batasan Anda adalah Anda tidak dapat memberikan variabel atau konstanta anggota dan tidak ada pengiriman dinamis .
Contoh dari teknik ini adalah:
Perhatikan bahwa ini menyediakan "kelas abstrak" seperti fitur bahkan untuk struct, tetapi kelas juga dapat mengimplementasikan protokol yang sama.
Juga perhatikan bahwa setiap kelas atau struct yang mengimplementasikan protokol Karyawan harus menyatakan properti AnnualSalary lagi.
Yang terpenting, perhatikan bahwa tidak ada pengiriman dinamis . Ketika
logSalary
dipanggil pada instance yang disimpan sebagaiSoftwareEngineer
panggilan metode versi ditimpa. KetikalogSalary
dipanggil pada instance setelah di-cast keEmployee
, ia memanggil implementasi asli (itu tidak secara dinamis mengirimkan ke versi yang diganti meskipun instance sebenarnya aSoftware Engineer
.Untuk informasi lebih lanjut, lihat video WWDC yang luar biasa tentang fitur itu: Membangun Aplikasi yang Lebih Baik dengan Jenis Nilai di Swift
sumber
protocol Animal { var property : Int { get set } }
. Anda juga dapat meninggalkan set jika Anda tidak ingin properti memiliki setterfunc logSalary()
ke deklarasi protokol Karyawan, contoh mencetakoverridden
untuk kedua panggilanlogSalary()
. Ini ada di Swift 3.1. Dengan demikian Anda mendapatkan manfaat polimorfisme. Metode yang benar disebut dalam kedua kasus.Perhatikan bahwa jawaban ini ditargetkan pada Swift 2.0 ke atas
Anda dapat mencapai perilaku yang sama dengan protokol dan ekstensi protokol.
Pertama, Anda menulis protokol yang berfungsi sebagai antarmuka untuk semua metode yang harus diimplementasikan dalam semua jenis yang sesuai dengannya.
Kemudian Anda bisa menambahkan perilaku default ke semua jenis yang sesuai dengannya
Anda sekarang dapat membuat tipe baru dengan mengimplementasikan
Drivable
.Jadi pada dasarnya Anda mendapatkan:
Drivable
implementasispeed
Drivable
(accelerate
)Drivable
dijamin tidak akan dipakai karena itu hanya protokolModel ini sebenarnya berperilaku jauh lebih seperti ciri-ciri, yang berarti Anda dapat menyesuaikan diri dengan beberapa protokol dan mengambil implementasi default dari salah satu dari mereka, sedangkan dengan superclass abstrak Anda terbatas pada hirarki kelas yang sederhana.
sumber
UICollectionViewDatasource
,. Saya ingin menghapus semua boilerplate dan merangkumnya dalam protokol / ekstensi terpisah dan kemudian digunakan kembali oleh beberapa kelas. Faktanya, pola templat akan sempurna di sini, tapi ...Saya pikir ini adalah yang terdekat dengan Java
abstract
atau C #abstract
:Perhatikan bahwa, agar
private
pengubah berfungsi, Anda harus mendefinisikan kelas ini dalam file Swift yang terpisah.EDIT: Namun, kode ini tidak memungkinkan untuk mendeklarasikan metode abstrak dan karenanya memaksakan implementasinya.
sumber
Cara paling sederhana adalah dengan menggunakan panggilan ke
fatalError("Not Implemented")
dalam metode abstrak (bukan variabel) pada ekstensi protokol.sumber
(MyConcreteClass() as MyInterface).myMethod()
tetapi itu berhasil! Kuncinya termasukmyMethod
dalam deklarasi protokol; jika tidak panggilan akan crash.Setelah saya berjuang selama beberapa minggu, saya akhirnya menyadari bagaimana menerjemahkan kelas abstrak Java / PHP ke Swift:
Namun saya pikir Apple tidak menerapkan kelas abstrak karena umumnya menggunakan pola + protokol delegasi sebagai gantinya. Misalnya pola yang sama di atas akan lebih baik dilakukan seperti ini:
Saya membutuhkan pola seperti ini karena saya ingin menyamakan beberapa metode di UITableViewController seperti viewWillAppear dll. Apakah ini membantu?
sumber
Ada cara untuk mensimulasikan kelas abstrak menggunakan Protokol. Ini adalah sebuah contoh:
sumber
Satu lagi cara Anda bisa mengimplementasikan kelas abstrak adalah dengan memblokir initializer. Saya telah melakukannya dengan cara ini:
sumber
Saya mencoba membuat
Weather
kelas abstrak, tetapi menggunakan protokol tidak ideal karena saya harus menulisinit
metode yang sama berulang kali. Memperluas protokol dan menulisinit
metode memiliki masalah, terutama karena saya menggunakanNSObject
penyesuaianNSCoding
.Jadi saya datang dengan ini untuk
NSCoding
kesesuaian:Adapun
init
:sumber
Pindahkan semua referensi ke properti abstrak dan metode kelas Base ke implementasi ekstensi protokol, di mana Self membatasi ke kelas Base. Anda akan mendapatkan akses ke semua metode dan properti kelas Base. Selain itu kompiler memeriksa implementasi metode dan properti abstrak dalam protokol untuk kelas turunan
sumber
Dengan batasan tidak ada pengiriman dinamis, Anda dapat melakukan sesuatu seperti ini:
sumber