Einstufige Objekterstellung und Eigenschaftsinitialisierung in Swift?




swift let (4)

Wenn für Ihre Klasse kein Initialisierer erforderlich ist, können Sie die Student-Eigenschaften mithilfe einer closure-Methode festlegen, bevor Sie das neue Student-Objekt wie folgt zurückgeben:

public class Student {
    var firstName = String()
    var lastName = String()
}

let student1 = Student()
let student2: Student  = {
    let student = Student()
    student.firstName = "John"
    student.lastName  = "Doe"
    return student
}()

print(student2.firstName)  // John
print(student2.lastName)  // Doe

Gibt es eine Möglichkeit, einer Klasseninstanz Eigenschaftenwerte zuzuweisen, auch wenn es sich nicht um einen Parameter im init-Konstruktor handelt? Zum Beispiel kann ich in C # dies tun:

public class Student
{
   public string firstName;
   public string lastName;
}

var student1 = new Student();
var student2 = new Student { firstName = "John", lastName  = "Doe" };

Hinweis für student2 Ich kann noch während der Initialisierung Werte zuweisen, obwohl es keinen Konstruktor in der Klasse gibt.

Ich konnte in der Dokumentation nicht finden, ob du so etwas für Swift machen kannst. Wenn nicht, gibt es eine Möglichkeit, extensions zu verwenden, um die Student Klasse so zu erweitern, dass während der Initialisierung Eigenschaftswerte zugewiesen werden?

Der Grund warum ich das suche, ist, dass ich ein Array von Instanzen zu einem Array hinzufügen kann, ohne explizit Variablen für jede Studenteninstanz zu erstellen, so:

var list = new[] {
  new Student { firstName = "John", lastName  = "Doe" },
  new Student { firstName = "Jane", lastName  = "Jones" },
  new Student { firstName = "Jason", lastName  = "Smith" }
}

Ein nativer oder eleganter Weg dies in Swift zu erreichen?


Answer #1

Je nachdem, wie Sie diesen Typ konfigurieren möchten und welche Syntax für Sie am bequemsten ist, haben Sie mehrere Möglichkeiten.

Sie könnten einen geeigneten Initialisierer definieren, der die Eigenschaften akzeptiert, die Sie festlegen möchten. Nützlich, wenn Sie immer die gleichen Eigenschaften festlegen, weniger nützlich, wenn Sie einen inkonsistenten Satz optionaler Eigenschaften festlegen.

public class Student
{
    public var firstName:String?;
    public var lastName:String?;
}

extension Student {
    convenience init(firstName: String, lastName: String) {
        self.init()
        self.firstName = firstName
        self.lastName = lastName
    }
}

Student(firstName: "Any", lastName: "Body")

Sie könnten einen Convenience-Initialisierer definieren, der einen Block zum Konfigurieren der neuen Instanz akzeptiert.

extension Student {
    convenience init(_ configure: (Student) -> Void ) {
        self.init()
        configure(self)
    }
}

Student( { $0.firstName = "Any"; $0.lastName = "Body" } )

Sie können Rubys tap Methode als Erweiterung imitieren, sodass Sie ein Objekt in der Mitte einer Methodenkette bearbeiten können.

extension Student {
    func tap(block: (Student) -> Void) -> Self {
        block(self)
        return self
    }
}

Student().tap({ $0.firstName = "Any"; $0.lastName = "body"})

Wenn das letzte nützlich ist, möchten Sie vielleicht in der Lage sein, auf ein Objekt zu tap . Ich glaube nicht, dass Sie das automatisch tun können, aber Sie können eine Standardimplementierung definieren, um es einfacher zu machen:

protocol Tap: AnyObject {}

extension Tap {
    func tap(block: (Self) -> Void) -> Self {
        block(self)
        return self
    }
}

extension Student: Tap {}

Student().tap({ $0.firstName = "Any"; $0.lastName = "body"})

Answer #2

Ich wollte nur darauf hinweisen, dass, wenn Ihre Struktur unveränderlich sein kann, Sie einfach eine struct anstelle einer class und Sie einen impliziten Initializer erhalten:

Fügen Sie das einfach in einen Spielplatz ein und ändern Sie struct in class und Sie werden sehen, was ich meine.

struct Student
{
    var firstName : String?
    var lastName : String?
}

var student = Student(firstName: "Dan", lastName: "Beaulieu")

Answer #3

Der Grund dafür ist, dass ich ein Array von Instanzen zu einem Array hinzufügen kann, ohne explizit Variablen für jede Schülerinstanz zu erstellen [.]

Ich bin nicht mit C # vertraut, aber in Swift können Sie das tun, indem Sie einfach die Objekte innerhalb der Array-Deklaration initialisieren:

var list: [Student] = [
    Student(firstName: "John", lastName: "Doe"),
    Student(firstName: "Jane", lastName: "Jones"),
    Student(firstName: "Jason", lastName: "Smith")
]

Die anderen vorgeschlagenen Ansätze sind alle gleichermaßen gültig, aber wenn Sie nur versuchen, ein Array zu bevölkern, ohne irgendwelche Variablen zu deklarieren, macht Swift das einfach.





instance