Ich würde nicht sagen, dass Structs weniger Funktionalität bieten.
Sicher, self ist unveränderlich, außer in einer mutierenden Funktion, aber das war's dann auch schon.
Vererbung funktioniert gut, solange man sich an die gute alte Idee hält, dass jede Klasse entweder abstrakt oder final sein sollte.
Implementieren Sie abstrakte Klassen als Protokolle und finale Klassen als Structs.
Das Gute an Structs ist, dass Sie Ihre Felder veränderbar machen können, ohne gemeinsamen veränderlichen Zustand zu erstellen, weil das Kopieren beim Schreiben sich darum kümmert :)
Deshalb sind die Eigenschaften / Felder im folgenden Beispiel alle veränderbar, was ich nicht in Java oder C# oder Swift Klassen machen würde.
Beispiel Vererbungsstruktur mit ein wenig schmutziger und direkter Verwendung am Ende in der Funktion namens "Beispiel":
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 Beispiel()
{
class Visitor : EventVisitor
{
var status: UInt32 = 3;
func visit(event: TimeEvent)
{
print("Ein Zeitereignis: \(event)")
}
func visit(event: StatusEvent)
{
print("Ein Statusereignis: \(event)")
if let change = event as? StatusChangedStatusEvent
{
status = change.newStatus
}
}
}
let visitor = Visitor()
readEvent(1).accept(visitor)
print("Status: \(visitor.status)")
}
13 Stimmen
Strukturen werden immer kopiert, wenn sie in Ihrem Code weitergereicht werden und verwenden kein Referenzzählen. Quelle: developer.apple.com/library/prerelease/ios/documentation/swift/…
4 Stimmen
Ich würde sagen, dass structs besser geeignet sind, um Daten zu speichern, nicht Logik. Um es in Java-Begriffen auszudrücken, stelle dir structs als "Value Objects" vor.
6 Stimmen
Ich bin erstaunt, dass im gesamten Gespräch nicht direkt auf copy-on-write oder lazy copy verwiesen wird. Eventuelle Bedenken in Bezug auf die Leistung beim Strukturkopieren sind aufgrund dieses Designs größtenteils obsolet.
5 Stimmen
Die Wahl einer Struktur über eine Klasse ist keine Frage der Meinung. Es gibt spezifische Gründe, eine davon zu wählen.
1 Stimmen
Ich empfehle dringend, Warum Array nicht threadSafe ist anzusehen. Dies ist relevant, da Arrays & Strukturen beide Werttypen sind. Alle Antworten hier erwähnen, dass mit Strukturen/Arrays/Werttypen niemals ein Thread-Sicherheitsproblem auftreten wird, aber es gibt einen Sonderfall, in dem dies der Fall ist.
0 Stimmen
Apple hat jetzt (ab 2019) einen Artikel, der diese Frage direkt anspricht Auswahl zwischen Strukturen und Klassen.
0 Stimmen
@DavidJames Die Programmiersprache Swift: Strukturen und Klassen: Strukturen und Aufzählungen sind Wertearten sagt: "Sammlungen, die von der Standardbibliothek definiert sind, wie Arrays, Dictionaries und Strings" (nicht alle Strukturen) verwenden die Copy-on-Write-Technik. Siehe Kopiert Swift bei allen Strukturen?
0 Stimmen
Abgesehen von Swift komme ich langsam zu dem Schluss, dass die Verwendung von Java als primäre Unterrichtssprache möglicherweise ein größeres Problem darstellt als ich in den späten 90ern gedacht habe. Vergessen wir Pointer (Arithmetik), es scheint ein vollständiges Verständnis dessen zu fehlen, was ein zusammengesetzter Werttyp ist und warum er wichtig ist. C# hat es sicherlich inkludiert, C und C++ haben es offensichtlich, aber es fehlt sowohl Java als auch seinem JVM, bis die Valhalla-Initiative übernimmt.