Dalam Swift, dapatkah seseorang menjelaskan cara menimpa properti pada superclass dengan objek lain yang disubklasifikasikan dari properti asli?
Ambil contoh sederhana ini:
class Chassis {}
class RacingChassis : Chassis {}
class Car {
let chassis = Chassis()
}
class RaceCar: Car {
override let chassis = RacingChassis() //Error here
}
Ini memberikan kesalahan:
Cannot override with a stored property 'chassis'
Jika saya memiliki sasis sebagai 'var', saya mendapatkan kesalahan:
Cannot override mutable property 'chassis' of type 'Chassis' with covariant type 'RacingChassis'
Satu-satunya hal yang dapat saya temukan dalam panduan di bawah "Overriding Properties" menunjukkan bahwa kita harus mengganti pengambil dan penyetel, yang mungkin berfungsi untuk mengubah nilai properti (jika itu 'var'), tetapi bagaimana dengan mengubah kelas properti ?
strong
properti dan saya mendapatkan kesalahan saat mencoba menimpanya - tetapi sepertinya saya melewatkan bahwa itu diterjemahkan ke "opsional yang tidak terbuka secara implisit" (chassis!
) di Cepat, jadioverride var chassis : Chassis!
perbaiki.Ini sepertinya berhasil
sumber
let
di dalamCar
kelas yang membuatnya tidak mungkin untuk diubah. Kami hanya dapat mengubahchassis
properti diRaceCar
kelas.Coba ini:
Kemudian:
Detail dalam http://www.mylonly.com/14957025459875.html
sumber
Solusi Dash yang disediakan berfungsi dengan baik kecuali bahwa kelas super harus dideklarasikan dengan kata kunci let dan bukan var. Berikut ini adalah solusi yang mungkin tetapi TIDAK DIANJURKAN!
Solusi di bawah ini akan dikompilasi dengan Xcode 6.2, SWIFT 1.1 (jika semua kelas dalam file swift yang berbeda) tetapi harus dihindari karena ITU BISA MENUJU PERILAKU YANG TAK TERKENAL (TERMASUK CRASH, terutama ketika menggunakan tipe non-opsional). CATATAN: INI TIDAK BEKERJA DENGAN XCODE 6.3 BETA 3, SWIFT 1.2
sumber
Secara teoritis, Anda diizinkan melakukannya dengan cara ini ...
Ini berfungsi dengan baik di taman bermain Xcode.
Tetapi , jika Anda mencoba ini di proyek nyata, kesalahan kompiler memberitahu Anda:
Saya hanya memeriksa Xcode 6.0 GM sampai sekarang.
Sayangnya, Anda harus menunggu sampai Apple memperbaikinya.
Saya telah mengirimkan laporan bug juga. 18518795
sumber
Saya telah melihat banyak alasan mengapa mendesain API menggunakan variabel alih-alih fungsi itu bermasalah dan bagi saya menggunakan properti yang dikomputasi terasa seperti solusi. Ada alasan bagus untuk menjaga agar variabel instan Anda tetap dienkapsulasi. Di sini saya telah membuat protokol Automobile yang sesuai dengan Mobil. Protokol ini memiliki metode accessor yang mengembalikan objek Chassis. Karena Mobil sesuai dengannya, subkelas RaceCar dapat menimpanya dan mengembalikan subkelas Chassis yang berbeda. Ini memungkinkan kelas Mobil memprogram ke antarmuka (Otomotif) dan kelas RaceCar yang tahu tentang RacingChassis dapat mengakses variabel _racingChassis secara langsung.
Contoh lain mengapa mendesain API menggunakan variabel rusak adalah ketika Anda memiliki variabel dalam protokol. Jika Anda ingin membagi semua fungsi protokol menjadi ekstensi yang Anda bisa, kecuali properti yang disimpan tidak dapat ditempatkan dalam ekstensi dan harus didefinisikan di kelas (untuk mendapatkan ini untuk dikompilasi Anda harus membatalkan komentar kode di Kelas AdaptableViewController dan hapus variabel mode dari ekstensi):
Kode di atas akan memiliki kesalahan kompiler ini: "Ekstensi mungkin tidak memiliki properti yang disimpan". Inilah cara Anda dapat menulis ulang contoh di atas sehingga segala sesuatu dalam protokol dapat dipisahkan dalam ekstensi dengan menggunakan fungsi sebagai gantinya:
sumber
Anda dapat mencapainya dengan menggunakan obat generik:
Dengan pendekatan ini Anda akan memiliki 100% jenis kode aman tanpa paksaan membuka.
Tetapi ini adalah jenis peretasan, dan jika Anda perlu mendefinisikan ulang beberapa properti daripada deklarasi kelas Anda akan terlihat seperti kekacauan total. Jadi berhati-hatilah dengan pendekatan ini.
sumber
Bergantung pada bagaimana Anda berencana menggunakan properti, cara paling sederhana untuk melakukan ini adalah dengan menggunakan tipe opsional untuk subkelas Anda, dan mengganti
didSet {}
metode untuk super:Jelas Anda perlu meluangkan waktu memeriksa untuk memastikan kelas dapat diinisialisasi dengan cara ini, tetapi dengan mengatur properti menjadi opsional, Anda melindungi diri sendiri terhadap situasi di mana casting tidak lagi berfungsi.
sumber
Anda cukup membuat variabel lain dari RacingChassis.
sumber
chassis
dan memungkinkan kita untuk mendapatkan / mengaturRacingChassis
contoh kita denganchassis
properti.Coba ini:
sumber
sumber
Berikut ini memungkinkan objek tunggal untuk digunakan dalam kelas dasar dan turunan. Di kelas turunan, gunakan properti objek turunan.
sumber
Variasi sedikit dari jawaban lain, tetapi lebih sederhana dan lebih aman dengan beberapa manfaat yang bagus.
Manfaatnya termasuk bahwa tidak ada batasan pada apa sasis harus (var, biarkan, opsional, dll), dan mudah untuk subkelas RaceCar. Subclass dari RaceCar kemudian dapat memiliki nilai yang dihitung sendiri untuk sasis (atau racingChassis).
sumber
cukup tetapkan properti imageview baru dengan konvensi penamaan yang berbeda seperti imgview karena imageView sudah menjadi miliknya sendiri dan kami tidak dapat menetapkan 2 properti kuat.
sumber