Apakah ada cara standar untuk membuat "fungsi virtual murni" di Swift, yaitu. salah satu yang harus diganti oleh setiap subclass, dan yang mana, jika tidak, menyebabkan kesalahan waktu kompilasi?
swift
abstract
swift-protocols
JuJoDi
sumber
sumber
protocol
s (dibandingkan denganinterface
s di Java) Jika Anda perlu menggunakannya seperti metode abstrak, lihat pertanyaan / jawaban ini: stackoverflow.com/a/39038828/2435872Jawaban:
Anda memiliki dua pilihan:
1. Gunakan Protokol
Tentukan superclass sebagai Protokol, bukan sebagai Kelas
Pro : Pemeriksaan waktu kompilasi apakah setiap "subclass" (bukan subclass sebenarnya) mengimplementasikan metode yang diperlukan
Kontra : "superclass" (protokol) tidak dapat mengimplementasikan metode atau properti
2. Tegaskan dalam versi super dari metode ini
Contoh:
class SuperClass { func someFunc() { fatalError("Must Override") } } class Subclass : SuperClass { override func someFunc() { } }
Pro : Dapat mengimplementasikan metode dan properti di superclass
Kontra : Tidak ada pemeriksaan waktu kompilasi
sumber
fatalError
tidak menyediakan pemeriksaan waktu kompilasi, sebaiknya kompilator setidaknya cukup pintar untuk tidak meminta Anda memberikan nilai kembalian untuk metode saat jalur eksekusi memanggilfatalError
.super.someFunc()
dari metode yang ditimpa, Anda mendapatkan kesalahan meskipun Anda menimpanya. Anda tahu bahwa Anda tidak seharusnya menyebutnya, tetapi orang lain tidak harus mengetahuinya dan hanya mengikuti praktik standar.Hal berikut memungkinkan untuk mewarisi dari kelas dan juga memiliki pemeriksaan waktu kompilasi protokol :)
protocol ViewControllerProtocol { func setupViews() func setupConstraints() } typealias ViewController = ViewControllerClass & ViewControllerProtocol class ViewControllerClass : UIViewController { override func viewDidLoad() { self.setup() } func setup() { guard let controller = self as? ViewController else { return } controller.setupViews() controller.setupConstraints() } //.... and implement methods related to UIViewController at will } class SubClass : ViewController { //-- in case these aren't here... an error will be presented func setupViews() { ... } func setupConstraints() { ... } }
sumber
Tidak ada dukungan untuk kelas abstrak / fungsi virtual, tetapi Anda mungkin dapat menggunakan protokol untuk banyak kasus:
protocol SomeProtocol { func someMethod() } class SomeClass: SomeProtocol { func someMethod() {} }
Jika SomeClass tidak mengimplementasikan someMethod, Anda akan mendapatkan error waktu kompilasi ini:
error: type 'SomeClass' does not conform to protocol 'SomeProtocol'
sumber
Solusi lain, jika Anda tidak memiliki terlalu banyak metode "virtual", adalah membuat subclass meneruskan "implementasi" ke konstruktor kelas dasar sebagai objek fungsi:
class MyVirtual { // 'Implementation' provided by subclass let fooImpl: (() -> String) // Delegates to 'implementation' provided by subclass func foo() -> String { return fooImpl() } init(fooImpl: (() -> String)) { self.fooImpl = fooImpl } } class MyImpl: MyVirtual { // 'Implementation' for super.foo() func myFoo() -> String { return "I am foo" } init() { // pass the 'implementation' to the superclass super.init(myFoo) } }
sumber
Anda dapat menggunakan protokol vs pernyataan seperti yang disarankan dalam jawaban di sini oleh
drewag
. Namun, contoh untuk protokolnya hilang. Saya menutupi di sini,Protokol
protocol SomeProtocol { func someMethod() } class SomeClass: SomeProtocol { func someMethod() {} }
Sekarang setiap subclass diharuskan mengimplementasikan protokol yang diperiksa dalam waktu kompilasi. Jika SomeClass tidak mengimplementasikan someMethod, Anda akan mendapatkan error waktu kompilasi ini:
Catatan: ini hanya berfungsi untuk kelas paling atas yang mengimplementasikan protokol. Setiap subclass dapat mengabaikan persyaratan protokol. - seperti yang dikomentari oleh
memmons
Tuntutan
class SuperClass { func someFunc() { fatalError("Must Override") } } class Subclass : SuperClass { override func someFunc() { } }
Namun, pernyataan hanya akan berfungsi pada waktu proses.
sumber
Karena baru dalam pengembangan iOS, saya tidak sepenuhnya yakin kapan ini diterapkan, tetapi salah satu cara untuk mendapatkan yang terbaik dari kedua dunia adalah dengan menerapkan ekstensi untuk protokol:
protocol ThingsToDo { func doThingOne() } extension ThingsToDo { func doThingTwo() { /* Define code here */} } class Person: ThingsToDo { func doThingOne() { // Already defined in extension doThingTwo() // Rest of code } }
Ekstensi inilah yang memungkinkan Anda memiliki nilai default untuk suatu fungsi sementara fungsi dalam protokol reguler masih memberikan kesalahan waktu kompilasi jika tidak ditentukan
sumber