Bermain-main dengan Swift, yang berasal dari latar belakang Java, mengapa Anda ingin memilih Struct daripada Class? Sepertinya mereka adalah hal yang sama, dengan Struct yang menawarkan fungsionalitas yang lebih sedikit. Mengapa memilihnya?
Bermain-main dengan Swift, yang berasal dari latar belakang Java, mengapa Anda ingin memilih Struct daripada Class? Sepertinya mereka adalah hal yang sama, dengan Struct yang menawarkan fungsionalitas yang lebih sedikit. Mengapa memilihnya?
Jawaban:
Menurut WWDC 2015 talk Protocol Oriented Programming di Swift ( video , transkrip ) yang sangat populer , Swift menyediakan sejumlah fitur yang membuat struct lebih baik daripada kelas dalam banyak keadaan.
Structs lebih disukai jika mereka relatif kecil dan copiable karena menyalin jauh lebih aman daripada memiliki banyak referensi ke contoh yang sama seperti yang terjadi pada kelas. Ini sangat penting ketika memberikan variabel ke banyak kelas dan / atau dalam lingkungan multithreaded. Jika Anda selalu dapat mengirim salinan variabel Anda ke tempat lain, Anda tidak perlu khawatir tentang tempat lain yang mengubah nilai variabel Anda di bawah Anda.
Dengan Structs, ada jauh lebih sedikit perlu khawatir tentang kebocoran memori atau beberapa utas berlomba untuk mengakses / memodifikasi satu contoh variabel. (Untuk yang lebih berpikiran teknis, pengecualian untuk itu adalah ketika menangkap struct di dalam penutupan karena itu sebenarnya menangkap referensi ke instance kecuali Anda secara eksplisit menandai itu untuk disalin).
Kelas juga bisa membengkak karena kelas hanya bisa mewarisi dari superkelas tunggal. Itu mendorong kami untuk membuat kacamata super besar yang mencakup banyak kemampuan berbeda yang hanya terkait secara longgar. Menggunakan protokol, terutama dengan ekstensi protokol di mana Anda dapat menyediakan implementasi protokol, memungkinkan Anda untuk menghilangkan kebutuhan kelas untuk mencapai perilaku semacam ini.
Pembicaraan menjabarkan skenario ini di mana kelas lebih disukai:
- Menyalin atau membandingkan contoh tidak masuk akal (misalnya, Window)
- Seumur hidup Instance terkait dengan efek eksternal (misalnya, TemporaryFile)
- Contoh hanya "tenggelam" - saluran hanya menulis ke keadaan eksternal (egCGContext)
Ini menyiratkan bahwa struct harus menjadi default dan kelas harus menjadi mundur.
Di sisi lain, dokumentasi Bahasa Pemrograman Swift agak kontradiktif:
Instance struktur selalu dilewati oleh nilai, dan instance kelas selalu dilewati oleh referensi. Ini berarti bahwa mereka cocok untuk berbagai jenis tugas. Saat Anda mempertimbangkan konstruk data dan fungsionalitas yang Anda perlukan untuk suatu proyek, putuskan apakah setiap konstruk data harus didefinisikan sebagai kelas atau sebagai struktur.
Sebagai pedoman umum, pertimbangkan untuk membuat struktur ketika satu atau lebih kondisi ini berlaku:
- Tujuan utama struktur adalah untuk merangkum beberapa nilai data yang relatif sederhana.
- Adalah masuk akal untuk mengharapkan bahwa nilai-nilai yang dienkapsulasi akan disalin daripada dirujuk ketika Anda menetapkan atau membagikan turunan dari struktur itu.
- Setiap properti yang disimpan oleh struktur itu sendiri adalah tipe nilai, yang juga diharapkan akan disalin daripada direferensikan.
- Struktur tidak perlu mewarisi properti atau perilaku dari tipe lain yang sudah ada.
Contoh kandidat yang baik untuk struktur meliputi:
- Ukuran bentuk geometris, mungkin merangkum properti lebar dan properti tinggi, keduanya bertipe Double.
- Cara untuk merujuk ke rentang dalam rangkaian, mungkin merangkum properti awal dan properti panjang, keduanya dari tipe Int.
- Suatu titik dalam sistem koordinat 3D, mungkin merangkum properti x, y dan z, masing-masing bertipe Double.
Dalam semua kasus lain, tentukan kelas, dan buat instance kelas tersebut untuk dikelola dan diteruskan dengan referensi. Dalam praktiknya, ini berarti bahwa sebagian besar konstruk data khusus harus kelas, bukan struktur.
Di sini dikatakan bahwa kita harus menggunakan kelas secara default dan menggunakan struktur hanya dalam keadaan tertentu. Pada akhirnya, Anda perlu memahami implikasi dunia nyata dari tipe nilai vs tipe referensi dan kemudian Anda dapat membuat keputusan tentang kapan harus menggunakan struct atau kelas. Juga, perlu diingat bahwa konsep-konsep ini selalu berkembang dan dokumentasi Bahasa Pemrograman Swift ditulis sebelum ceramah Pemrograman Berorientasi Protokol diberikan.
In practice, this means that most custom data constructs should be classes, not structures.
Bisakah Anda menjelaskan kepada saya bagaimana, setelah membaca itu, Anda mendapatkan bahwa sebagian besar set data harus struktur dan bukan kelas? Mereka memberikan seperangkat aturan khusus ketika sesuatu harus menjadi struct dan cukup banyak mengatakan "semua skenario lain kelas lebih baik."
Karena instance struct dialokasikan pada stack, dan instance kelas dialokasikan pada heap, struct kadang-kadang dapat secara drastis lebih cepat.
Namun, Anda harus selalu mengukurnya sendiri dan memutuskan berdasarkan kasus penggunaan unik Anda.
Pertimbangkan contoh berikut, yang menunjukkan 2 strategi pembungkus Int
tipe data menggunakan struct
dan class
. Saya menggunakan 10 nilai berulang untuk lebih mencerminkan dunia nyata, di mana Anda memiliki banyak bidang.
class Int10Class {
let value1, value2, value3, value4, value5, value6, value7, value8, value9, value10: Int
init(_ val: Int) {
self.value1 = val
self.value2 = val
self.value3 = val
self.value4 = val
self.value5 = val
self.value6 = val
self.value7 = val
self.value8 = val
self.value9 = val
self.value10 = val
}
}
struct Int10Struct {
let value1, value2, value3, value4, value5, value6, value7, value8, value9, value10: Int
init(_ val: Int) {
self.value1 = val
self.value2 = val
self.value3 = val
self.value4 = val
self.value5 = val
self.value6 = val
self.value7 = val
self.value8 = val
self.value9 = val
self.value10 = val
}
}
func + (x: Int10Class, y: Int10Class) -> Int10Class {
return IntClass(x.value + y.value)
}
func + (x: Int10Struct, y: Int10Struct) -> Int10Struct {
return IntStruct(x.value + y.value)
}
Kinerja diukur menggunakan
// Measure Int10Class
measure("class (10 fields)") {
var x = Int10Class(0)
for _ in 1...10000000 {
x = x + Int10Class(1)
}
}
// Measure Int10Struct
measure("struct (10 fields)") {
var y = Int10Struct(0)
for _ in 1...10000000 {
y = y + Int10Struct(1)
}
}
func measure(name: String, @noescape block: () -> ()) {
let t0 = CACurrentMediaTime()
block()
let dt = CACurrentMediaTime() - t0
print("\(name) -> \(dt)")
}
Kode dapat ditemukan di https://github.com/knguyen2708/StructVsClassPerformance
UPDATE (27 Mar 2018) :
Mulai dari Swift 4.0, Xcode 9.2, menjalankan Release build di iPhone 6S, iOS 11.2.6, pengaturan Swift Compiler adalah -O -whole-module-optimization
:
class
versi butuh 2,06 detikstruct
versi butuh 4,17e-08 detik (50.000.000 kali lebih cepat)(Saya tidak lagi menjalankan berulang rata-rata, karena varians sangat kecil, di bawah 5%)
Catatan : perbedaannya jauh lebih dramatis tanpa optimasi seluruh modul. Saya akan senang jika seseorang dapat menunjukkan apa yang sebenarnya dilakukan oleh bendera.
PEMBARUAN (7 Mei 2016) :
Pada Swift 2.2.1, Xcode 7.3, menjalankan Release build di iPhone 6S, iOS 9.3.1, rata-rata lebih dari 5 run, pengaturan Swift Compiler adalah -O -whole-module-optimization
:
class
versi mengambil 2.159942142sstruct
versi mengambil 5.83E-08s (37.000.000 kali lebih cepat)Catatan : ketika seseorang menyebutkan bahwa dalam skenario dunia nyata, kemungkinan akan ada lebih dari 1 bidang dalam sebuah struct, saya telah menambahkan tes untuk struct / kelas dengan 10 bidang alih-alih 1. Anehnya, hasilnya tidak banyak berbeda.
HASIL ASLI (1 Juni 2014):
(Berlari pada struct / kelas dengan 1 bidang, bukan 10)
Pada Swift 1.2, Xcode 6.3.2, menjalankan Release build di iPhone 5S, iOS 8.3, rata-rata lebih dari 5 run
class
versi mengambil 9,788332333sstruct
versi mengambil 0,010532942s (900 kali lebih cepat)HASIL LAMA (dari waktu yang tidak diketahui)
(Berlari pada struct / kelas dengan 1 bidang, bukan 10)
Dengan rilis rilis di MacBook Pro saya:
class
Versi mengambil 1,10082 detikstruct
Versi mengambil 0,02324 detik (50 kali lebih cepat)Saya membuat inti untuk ini dengan contoh-contoh sederhana. https://github.com/objc-swift/swift-classes-vs-strures
struktur tidak dapat mewarisi dengan cepat. jika kamu mau
class Vehicle{
}
class Car : Vehicle{
}
Pergi untuk kelas.
Struktur cepat melewati nilai dan instance kelas melewati referensi.
Konstanta dan variabel struktur
Contoh (Digunakan di WWDC 2014)
struct Point{
var x = 0.0;
var y = 0.0;
}
Menentukan struct yang disebut Point.
var point = Point(x:0.0,y:2.0)
Sekarang jika saya mencoba mengubah x. Itu ungkapan yang valid.
point.x = 5
Tetapi jika saya mendefinisikan suatu titik sebagai konstanta.
let point = Point(x:0.0,y:2.0)
point.x = 5 //This will give compile time error.
Dalam hal ini seluruh titik konstan konstan.
Jika saya menggunakan Point kelas sebagai gantinya ini adalah ekspresi yang valid. Karena dalam sebuah kelas konstanta yang tetap adalah referensi ke kelas itu sendiri, bukan variabel instansinya (Kecuali variabel-variabel tersebut didefinisikan sebagai konstanta)
Berikut adalah beberapa alasan lain untuk dipertimbangkan:
struct mendapatkan penginisialisasi otomatis yang tidak harus Anda pertahankan dalam kode sama sekali.
struct MorphProperty {
var type : MorphPropertyValueType
var key : String
var value : AnyObject
enum MorphPropertyValueType {
case String, Int, Double
}
}
var m = MorphProperty(type: .Int, key: "what", value: "blah")
Untuk mendapatkan ini di kelas, Anda harus menambahkan inisialisasi, dan mempertahankan intializer ...
Jenis koleksi dasar seperti Array
struct. Semakin banyak Anda menggunakannya dalam kode Anda sendiri, semakin Anda akan terbiasa melewati nilai dibandingkan dengan referensi. Contohnya:
func removeLast(var array:[String]) {
array.removeLast()
println(array) // [one, two]
}
var someArray = ["one", "two", "three"]
removeLast(someArray)
println(someArray) // [one, two, three]
Rupanya kekekalan vs ketidakmampuan adalah topik yang besar, tetapi banyak orang pintar berpikir kekekalan - struct dalam hal ini - lebih disukai. Dapat berubah vs objek yang tidak berubah
internal
lingkup.
mutating
Anda secara eksplisit tentang fungsi apa yang mengubah keadaan mereka. Tetapi sifat mereka sebagai tipe nilai adalah yang penting. Jika Anda mendeklarasikan struct dengan let
Anda tidak dapat memanggil fungsi yang bermutasi padanya. Video WWDC 15 tentang pemrograman yang lebih baik melalui tipe nilai adalah sumber yang bagus untuk ini.
Dengan asumsi bahwa kita tahu Struct adalah tipe nilai dan Kelas adalah tipe referensi .
Jika Anda tidak tahu apa tipe nilai dan tipe referensi, lalu lihat Apa perbedaan antara meneruskan dengan referensi vs meneruskan dengan nilai?
Berdasarkan pos mikeash :
... Mari kita lihat beberapa contoh ekstrem dan nyata terlebih dahulu. Bilangan bulat jelas dapat disalin. Mereka harus menjadi tipe nilai. Soket jaringan tidak dapat disalin dengan bijaksana. Mereka harus menjadi tipe referensi. Poin, seperti dalam pasangan x, y, dapat disalin. Mereka harus menjadi tipe nilai. Pengontrol yang mewakili disk tidak dapat disalin dengan bijaksana. Itu harus menjadi tipe referensi.
Beberapa jenis dapat disalin tetapi mungkin bukan sesuatu yang Anda inginkan terjadi setiap saat. Ini menunjukkan bahwa mereka harus menjadi tipe referensi. Misalnya, tombol pada layar secara konseptual dapat disalin. Salinan tidak akan sama persis dengan aslinya. Klik pada salinan tidak akan mengaktifkan aslinya. Salinan tidak akan menempati lokasi yang sama di layar. Jika Anda melewatkan tombol atau memasukkannya ke variabel baru, Anda mungkin ingin merujuk ke tombol asli, dan Anda hanya ingin membuat salinan ketika diminta secara eksplisit. Itu berarti bahwa jenis tombol Anda harus menjadi jenis referensi.
Pengontrol tampilan dan jendela adalah contoh serupa. Mereka mungkin dapat disalin, mungkin, tetapi hampir tidak pernah apa yang ingin Anda lakukan. Mereka harus menjadi tipe referensi.
Bagaimana dengan tipe model? Anda mungkin memiliki tipe Pengguna yang mewakili pengguna di sistem Anda, atau tipe Kejahatan yang mewakili tindakan yang diambil oleh Pengguna. Ini cukup dapat disalin, jadi mereka mungkin harus tipe nilai. Namun, Anda mungkin ingin pembaruan Kejahatan Pengguna yang dibuat di satu tempat di program Anda agar dapat dilihat oleh bagian lain dari program ini. Ini menunjukkan bahwa Pengguna Anda harus dikelola oleh semacam pengontrol pengguna yang akan menjadi tipe referensi . misalnya
struct User {} class UserController { var users: [User] func add(user: User) { ... } func remove(userNamed: String) { ... } func ... }
Koleksi adalah kasus yang menarik. Ini termasuk hal-hal seperti array dan kamus, serta string. Apakah mereka dapat disalin? Jelas sekali. Apakah menyalin sesuatu yang Anda inginkan terjadi dengan mudah dan sering? Itu kurang jelas.
Sebagian besar bahasa mengatakan "tidak" untuk ini dan membuat jenis referensi koleksi mereka. Ini benar dalam Objective-C dan Java dan Python dan JavaScript dan hampir setiap bahasa lain yang bisa saya pikirkan. (Satu pengecualian utama adalah C ++ dengan tipe koleksi STL, tetapi C ++ adalah orang gila yang mengoceh di dunia bahasa yang melakukan semuanya dengan aneh.)
Swift berkata "ya," yang berarti bahwa tipe seperti Array dan Kamus dan String adalah struct daripada kelas. Mereka disalin pada tugas, dan meneruskannya sebagai parameter. Ini adalah pilihan yang sepenuhnya masuk akal asalkan salinannya murah, yang berusaha dengan susah payah dicapai oleh Swift. ...
Saya pribadi tidak memberi nama kelas saya seperti itu. Saya biasanya menamai UserManager milik saya alih-alih UserController tetapi idenya sama
Selain itu, jangan gunakan kelas ketika Anda harus menimpa setiap contoh fungsi yaitu mereka tidak memiliki fungsionalitas bersama .
Jadi alih-alih memiliki beberapa subclass dari suatu kelas. Gunakan beberapa struct yang sesuai dengan protokol.
Kasus wajar lainnya untuk struct adalah ketika Anda ingin melakukan delta / diff dari model lama dan baru Anda. Dengan tipe referensi Anda tidak dapat melakukannya di luar kotak. Dengan tipe nilai, mutasi tidak dibagikan.
Beberapa keuntungan:
Struktur jauh lebih cepat daripada Kelas. Juga, jika Anda membutuhkan warisan maka Anda harus menggunakan Kelas. Poin paling penting adalah bahwa Kelas adalah tipe referensi sedangkan Struktur adalah tipe nilai. sebagai contoh,
class Flight {
var id:Int?
var description:String?
var destination:String?
var airlines:String?
init(){
id = 100
description = "first ever flight of Virgin Airlines"
destination = "london"
airlines = "Virgin Airlines"
}
}
struct Flight2 {
var id:Int
var description:String
var destination:String
var airlines:String
}
sekarang mari kita buat instance dari keduanya.
var flightA = Flight()
var flightB = Flight2.init(id: 100, description:"first ever flight of Virgin Airlines", destination:"london" , airlines:"Virgin Airlines" )
sekarang mari kita lewati instance ini ke dua fungsi yang mengubah id, deskripsi, tujuan dll.
func modifyFlight(flight:Flight) -> Void {
flight.id = 200
flight.description = "second flight of Virgin Airlines"
flight.destination = "new york"
flight.airlines = "Virgin Airlines"
}
juga,
func modifyFlight2(flight2: Flight2) -> Void {
var passedFlight = flight2
passedFlight.id = 200
passedFlight.description = "second flight from virgin airlines"
}
begitu,
modifyFlight(flight: flightA)
modifyFlight2(flight2: flightB)
sekarang jika kita mencetak id dan deskripsi flightA, kita dapatkan
id = 200
description = "second flight of Virgin Airlines"
Di sini, kita dapat melihat id dan deskripsi FlightA diubah karena parameter yang diteruskan ke metode modifikasi sebenarnya menunjuk ke alamat memori objek flightA (tipe referensi).
sekarang jika kita mencetak id dan deskripsi instance FLightB yang kita dapatkan,
id = 100
description = "first ever flight of Virgin Airlines"
Di sini kita dapat melihat bahwa instance FlightB tidak berubah karena dalam metode modFlight2, instance sebenarnya dari Flight2 melewati daripada referensi (tipe nilai).
Here we can see that the FlightB instance is not changed
Structs
sedang value type
dan Classes
sedangreference type
Gunakan value
tipe saat:
Gunakan reference
tipe saat:
Informasi lebih lanjut dapat ditemukan di dokumentasi Apple
https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html
informasi tambahan
Jenis nilai cepat disimpan di tumpukan. Dalam suatu proses, setiap utas memiliki ruang tumpukannya sendiri, jadi tidak ada utas lain yang dapat mengakses tipe nilai Anda secara langsung. Karenanya tidak ada kondisi balapan, kunci, deadlock atau kompleksitas sinkronisasi utas terkait.
Tipe nilai tidak memerlukan alokasi memori dinamis atau penghitungan referensi, yang keduanya merupakan operasi yang mahal. Pada saat yang sama metode pada tipe nilai dikirim secara statis. Ini menciptakan keuntungan besar dalam mendukung tipe nilai dalam hal kinerja.
Sebagai pengingat di sini adalah daftar Swift
Jenis nilai:
Jenis referensi:
Menjawab pertanyaan dari sudut pandang tipe nilai vs tipe referensi, dari posting blog Apple ini akan tampak sangat sederhana:
Gunakan tipe nilai [mis. Struct, enum] ketika:
- Membandingkan data instan dengan == masuk akal
- Anda ingin salinan memiliki status independen
- Data akan digunakan dalam kode di beberapa utas
Gunakan tipe referensi [misalnya kelas] ketika:
- Membandingkan identitas instan dengan === masuk akal
- Anda ingin membuat status bersama yang dapat diubah
Seperti yang disebutkan dalam artikel itu, kelas tanpa properti yang dapat ditulisi akan berperilaku identik dengan struct, dengan (saya akan menambahkan) satu peringatan: struct adalah yang terbaik untuk model aman-thread - persyaratan yang semakin dekat dalam arsitektur aplikasi modern.
Dengan kelas Anda mendapatkan warisan dan diteruskan dengan referensi, struct tidak memiliki warisan dan diteruskan oleh nilai.
Ada sesi WWDC hebat di Swift, pertanyaan khusus ini dijawab dengan sangat terperinci di salah satunya. Pastikan Anda menontonnya, karena kecepatan Anda akan jauh lebih cepat daripada panduan Bahasa atau iBook.
Saya tidak akan mengatakan bahwa struct menawarkan fungsionalitas yang lebih sedikit.
Tentu, diri tidak dapat diubah kecuali dalam fungsi yang bermutasi, tetapi hanya itu saja.
Warisan bekerja dengan baik selama Anda tetap pada gagasan lama yang baik bahwa setiap kelas harus abstrak atau final.
Menerapkan kelas abstrak sebagai protokol dan kelas akhir sebagai struct.
Yang menyenangkan tentang struct adalah bahwa Anda dapat membuat bidang Anda bisa berubah tanpa membuat keadaan yang bisa dibagikan bersama karena copy on write menangani hal itu :)
Itu sebabnya properti / bidang dalam contoh berikut semuanya bisa berubah, yang tidak akan saya lakukan di Java atau C # atau kelas swift .
Contoh struktur pewarisan dengan sedikit penggunaan kotor dan langsung di bagian bawah dalam fungsi bernama "contoh":
protocol EventVisitor
{
func visit(event: TimeEvent)
func visit(event: StatusEvent)
}
protocol Event
{
var ts: Int64 { get set }
func accept(visitor: EventVisitor)
}
struct TimeEvent : Event
{
var ts: Int64
var time: Int64
func accept(visitor: EventVisitor)
{
visitor.visit(self)
}
}
protocol StatusEventVisitor
{
func visit(event: StatusLostStatusEvent)
func visit(event: StatusChangedStatusEvent)
}
protocol StatusEvent : Event
{
var deviceId: Int64 { get set }
func accept(visitor: StatusEventVisitor)
}
struct StatusLostStatusEvent : StatusEvent
{
var ts: Int64
var deviceId: Int64
var reason: String
func accept(visitor: EventVisitor)
{
visitor.visit(self)
}
func accept(visitor: StatusEventVisitor)
{
visitor.visit(self)
}
}
struct StatusChangedStatusEvent : StatusEvent
{
var ts: Int64
var deviceId: Int64
var newStatus: UInt32
var oldStatus: UInt32
func accept(visitor: EventVisitor)
{
visitor.visit(self)
}
func accept(visitor: StatusEventVisitor)
{
visitor.visit(self)
}
}
func readEvent(fd: Int) -> Event
{
return TimeEvent(ts: 123, time: 56789)
}
func example()
{
class Visitor : EventVisitor
{
var status: UInt32 = 3;
func visit(event: TimeEvent)
{
print("A time event: \(event)")
}
func visit(event: StatusEvent)
{
print("A status event: \(event)")
if let change = event as? StatusChangedStatusEvent
{
status = change.newStatus
}
}
}
let visitor = Visitor()
readEvent(1).accept(visitor)
print("status: \(visitor.status)")
}
Di Swift, pola pemrograman baru telah diperkenalkan dikenal sebagai Protokol Berorientasi Pemrograman.
Pola Penciptaan:
Dalam cepat, Struct adalah tipe nilai yang dikloning secara otomatis. Oleh karena itu kita mendapatkan perilaku yang diperlukan untuk menerapkan pola prototipe secara gratis.
Sedangkan kelas adalah tipe referensi, yang tidak secara otomatis dikloning selama penugasan. Untuk mengimplementasikan pola prototipe, kelas harus mengadopsi NSCopying
protokol.
Salinan duplikat hanya referensi, yang menunjuk ke objek-objek sedangkan salinan duplikat jauh referensi objek.
Menerapkan salinan dalam untuk setiap jenis referensi telah menjadi tugas yang membosankan. Jika kelas menyertakan tipe referensi lebih lanjut, kita harus menerapkan pola prototipe untuk masing-masing properti referensi. Dan kemudian kita harus benar-benar menyalin seluruh grafik objek dengan mengimplementasikan NSCopying
protokol.
class Contact{
var firstName:String
var lastName:String
var workAddress:Address // Reference type
}
class Address{
var street:String
...
}
Dengan menggunakan struct dan enum , kami membuat kode kami lebih sederhana karena kami tidak harus menerapkan logika salin.
Banyak Cocoa API membutuhkan subkelas NSObject, yang memaksa Anda menggunakan kelas. Tetapi selain itu, Anda dapat menggunakan case-case berikut dari blog Swift Apple untuk memutuskan apakah akan menggunakan tipe nilai struct / enum atau tipe referensi kelas.
Satu hal yang tidak mendapat perhatian dalam jawaban ini adalah bahwa variabel yang memegang kelas vs sebuah struct bisa let
sementara masih memungkinkan perubahan pada properti objek, sementara Anda tidak bisa melakukan ini dengan sebuah struct.
Ini berguna jika Anda tidak ingin variabel menunjuk ke objek lain, tetapi masih perlu memodifikasi objek, yaitu dalam kasus memiliki banyak variabel instan yang ingin Anda perbarui satu demi satu. Jika itu adalah sebuah struct, Anda harus mengizinkan variabel untuk direset ke objek lain sama sekali menggunakan var
untuk melakukan ini, karena tipe nilai konstan di Swift memungkinkan nol mutasi, sedangkan tipe referensi (kelas) tidak berperilaku seperti ini.
Karena struct adalah tipe nilai dan Anda dapat membuat memori dengan sangat mudah yang menyimpan ke dalam stack. Bangunan dapat dengan mudah diakses dan setelah lingkup pekerjaan itu dengan mudah deallocated dari memori stack melalui pop dari atas stack. Di sisi lain kelas adalah tipe referensi yang menyimpan di heap dan perubahan yang dibuat dalam satu objek kelas akan berdampak pada objek lain karena mereka erat digabungkan dan tipe referensi. Semua anggota struktur adalah publik sedangkan semua anggota kelas adalah pribadi .
Kerugian dari struct adalah tidak dapat diwarisi.
Struktur dan kelas adalah tipe data yang ditentang pengguna
Secara default, struktur adalah publik sedangkan kelas adalah pribadi
Kelas mengimplementasikan prinsip enkapsulasi
Objek kelas dibuat pada memori tumpukan
Kelas digunakan untuk kegunaan kembali sedangkan struktur digunakan untuk mengelompokkan data dalam struktur yang sama
Struktur data anggota tidak dapat diinisialisasi secara langsung tetapi mereka dapat ditugaskan oleh luar struktur
Anggota data kelas dapat diinisialisasi secara langsung oleh konstruktor parameter kurang dan ditugaskan oleh konstruktor parameterized