Initializers in snel deel 1: (intro, convenience en aangewezen intializers)

Initialisatie is een enorm onderwerp om snel te behandelen. Ik zal proberen dit in dit artikel zoveel mogelijk te vereenvoudigen.

https://stocksnap.io/
Apple-documenten: initialisatie is het proces waarbij een instantie van een klasse, structuur of opsomming wordt voorbereid voor gebruik. Dit proces omvat het instellen van een beginwaarde voor elke opgeslagen eigenschap in die instantie en het uitvoeren van een andere installatie of initialisatie die vereist is voordat de nieuwe instantie klaar is voor gebruik.

Klassen en structuren moeten al hun opgeslagen eigenschappen instellen op een geschikte beginwaarde tegen de tijd dat een instantie van die klasse of structuur wordt gemaakt. Opgeslagen eigenschappen kunnen niet in een onbepaalde toestand worden achtergelaten.

initialiseerders

Initializers zijn net speciale methoden die kunnen worden aangeroepen om een ​​nieuw exemplaar van een bepaald type te maken.

In zijn eenvoudigste vorm is een initialisator een instantiemethode zonder parameters, geschreven met het sleutelwoord init:

in het() {
// voer hier wat initialisatie uit
}

Zoals ik eerder heb gezegd, kunnen opgeslagen eigenschappen niet in een onbepaalde toestand blijven. Sommige waarden moeten eraan worden toegewezen op het moment van initialisatie. Overweeg de volgende klasse:

enum Geslacht {
zaak man
zaak vrouwelijk
zaak onbekend
}
struct Human {
var geslacht: geslacht // dit is een opgeslagen eigenschap.
init (geslacht: geslacht) {
self.gender = geslacht
}
}
let human = Human (geslacht: .male)

Hier wijs ik een waarde toe aan het variabele geslacht op het moment van initialisatie in de initialisatie. Als u de init-methode niet gebruikt om de variabele geslacht een waarde toe te wijzen, moet u een van de volgende handelingen uitvoeren:

  • u moet de variabele op het moment van declaratie als standaardwaarde instellen.
var geslacht: geslacht =. mannelijk
  • Of u moet de variabele als optioneel opgeven.
var geslacht: geslacht?

Het doel is dat op het moment van initialisatie van een instantie alle eigenschappen moeten worden geïnitialiseerd.

Initialisatie aanpassen

We kunnen aangepaste initializers toevoegen aan een klasse met aangepaste invoerparameters en optionele eigenschapstypen.

We kunnen meer dan één initialisatie hebben op basis van onze vereiste, met verschillende parameternamen, typen enz.
struct Human {
var geslacht: geslacht
var leeftijd: Int = 10
init (geslacht: geslacht) {// initializer 1
self.gender = geslacht
}
init (age: Int) {// initializer 2
self.age = leeftijd
self.gender = .unknown
}
init (leeftijd: Int, geslacht: geslacht) {// initializer 3
self.age = leeftijd
self.gender = geslacht
}
}
// ------------------------------
let human = Human (geslacht: .male)
let human2 = Human (leeftijd: 20)
let human3 = Human (leeftijd: 40, geslacht: .male)
De snelle compiler zal op basis van het argumentlabel beslissen welke init-methode moet worden aangeroepen.

Merk op dat het niet mogelijk is om deze initializers aan te roepen zonder argumentlabels te gebruiken. Argumentenlabels moeten altijd in een initialisatieprogramma worden gebruikt als ze zijn gedefinieerd en het weglaten ervan is een compilatiefout:

let human4 = Human () // error: kan geen initialisatie voor type ‘Human’ aanroepen zonder argumenten
let human5 = Human (40, .male) // error: error: ontbrekende argumentlabels 'age: gender:' in gesprek

Initialisatieparameters zonder argumentlabels

Als u geen argumentlabel voor een initialisatieparameter wilt gebruiken, schrijft u een onderstrepingsteken (_) in plaats van een expliciet argumentlabel voor die parameter om het standaardgedrag te overschrijven.

Laten we nu een init-methode als volgt aan de klasse Mens toevoegen:

init (_ leeftijd: Int, _ geslacht: geslacht) {
self.age = leeftijd
self.gender = geslacht
}

Nu kunnen we bellen:

let human5 = Human (40, .male)

Standaardinitializers

Swift biedt een standaardinitialisatie voor elke structuur of klasse die standaardwaarden voor al zijn eigenschappen biedt en zelf niet ten minste één initialisatie biedt. De standaardinitializer maakt eenvoudig een nieuwe instantie met alle eigenschappen ingesteld op hun standaardwaarden.

Dit voorbeeld definieert een klasse met de naam ShoppingListItem, die de naam, hoeveelheid en aankoopstatus van een artikel in een boodschappenlijst samenvat:

class ShoppingListItem {
var name: String?
var hoeveelheid = 1
var gekocht = onwaar
}
var item = ShoppingListItem ()

Memberwise-initializers voor structuurtypen

Structuurtypen ontvangen automatisch een lidsgewijze initialisatie als ze geen van hun eigen aangepaste initialisatie definiëren.

Aandachtspunten:

  • Als we geen aangepaste initialisatie bieden, ontvangt de structuur een initialisatie voor leden, zelfs als deze eigenschappen heeft die geen standaardwaarden hebben.
  • Als we geen aangepaste initialisatie bieden, ontvangt de structuur een initialisatie voor leden, zelfs als deze eigenschappen met standaardwaarden heeft opgeslagen.

Overweeg een struct met de naam Grootte

struct Grootte {
var breedte, hoogte: dubbele // opgeslagen eigenschappen zonder standaardwaarden
}
-------- of --------------
struct Grootte {
var width = 10.0, height = 30.0 // opgeslagen eigenschappen met standaardwaarden
}

De eerste structuur heeft twee opgeslagen eigenschappen zonder standaardwaarden. De tweede structuur heeft twee opgeslagen eigenschappen met standaardwaarden opgegeven. Aangepaste initializers worden niet in beide gevallen gegeven. Om deze structuur te initialiseren, krijgen we een initialisatie per lid met breedte en hoogte als parameters:

let twoByTwo = Grootte (breedte: 2.0, hoogte: 2.0)
Als we een aangepaste init-methode bieden, moeten alle opgeslagen eigenschappen worden geïnitialiseerd zoals eerder in dit artikel is uitgelegd. Ook is de initialisator die lid is in dit geval niet toegankelijk. d.w.z; Als u een aangepaste initialisatie voor een waardetype definieert, hebt u niet langer toegang tot de standaardinitialisatie (of de initialisatie voor leden, als het een structuur is) voor dat type.
struct Grootte {
var breedte, hoogte: dubbel
in het(){
self.width = 10.0
zelfhoogte = 30.0
}
}
let sizeObj1 = Grootte (breedte: 2.0, hoogte: 2.0) // fout. argument doorgegeven om te bellen waarvoor geen argumenten nodig zijn
let sizeObj2 = Grootte () // succes.

Initialisatie delegatie voor waardetypes

Initializers kunnen andere initializers aanroepen om een ​​deel van de initialisatie van een instantie uit te voeren. Dit proces, bekend als initialisatie delegatie.

  • Waardetypes (structuren en opsommingen) ondersteunen geen overerving, en dus is hun initialisatieproces relatief eenvoudig, omdat ze alleen kunnen delegeren naar een andere initialisatie die ze zelf leveren.
  • Klassen kunnen erven van andere klassen, zoals beschreven in Overerving. Dit betekent dat klassen extra verantwoordelijkheden hebben om ervoor te zorgen dat alle opgeslagen eigenschappen die ze erven een geschikte waarde krijgen tijdens de initialisatie.

Voorbeeld:

In het volgende voorbeeld wordt een aangepaste rechthoekige structuur gedefinieerd om een ​​geometrische rechthoek weer te geven. Het voorbeeld vereist twee ondersteunende structuren genaamd Grootte en Punt, die beide standaardwaarden van 0,0 bieden voor al hun eigenschappen:

struct Grootte {
var breedte = 0,0, hoogte = 0,0
}
struct Point {
var x = 0,0, y = 0,0
}

U kunt de onderstaande Rect-structuur op een van de volgende drie manieren initialiseren - door de standaard nul-geïnitialiseerde originelen en eigenschapeigenschappen voor grootte te gebruiken, door een specifiek oorsprongspunt en -grootte op te geven of door een specifiek middelpunt en een specifieke grootte op te geven. Deze initialisatie-opties worden voorgesteld door drie aangepaste initialisatieprogramma's die deel uitmaken van de definitie van de Rectstructure:

struct Rect {
var origin = Point ()
var size = grootte ()
in het() {}
init (oorsprong: punt, maat: grootte) {
self.origin = oorsprong
self.size = maat
}
init (center: Point, size: Size) {
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 2)
self.init (origin: Point (x: originX, y: originY), size: size)
}
}

Aangewezen initialisatie- en handige initialisatieprogramma's

Alle opgeslagen eigenschappen van een klasse - inclusief alle eigenschappen die de klasse van zijn superklasse overneemt - moeten tijdens de initialisatie een initiële waarde krijgen.

Swift definieert twee soorten initialisatoren voor klassetypes om ervoor te zorgen dat alle opgeslagen eigenschappen een initiële waarde ontvangen.

  • Aangewezen initializers
  • Gemak initializers

Aangewezen initializers zijn de primaire initializers voor een klasse. Een aangewezen initialisatie initialiseert alle eigenschappen die door die klasse zijn geïntroduceerd en roept een geschikte initialisatie van de superklasse op om het initialisatieproces in de superklasse-keten voort te zetten.

Elke klasse moet ten minste één aangewezen initializer hebben.

Aangewezen initializers voor klassen worden op dezelfde manier geschreven als eenvoudige initializers voor waardetypes:

init (_parameters indien aanwezig_) {
}

Gemakinitializers zijn secundair en ondersteunen initializers voor een klas. U kunt een gemakkelijke initialisatie definiëren om een ​​aangewezen initialisatie uit dezelfde klasse aan te roepen als de gemakinitialisatie, waarbij sommige parameters van de aangewezen initialisatie zijn ingesteld op standaardwaarden. U kunt ook een gemakkelijke initialisatie definiëren om een ​​instantie van die klasse te maken voor een specifieke use case of invoerwaardetype.

U hoeft geen gemak-initializers te bieden als uw klas ze niet nodig heeft. Maak gemakinitializers wanneer een snelkoppeling naar een gemeenschappelijk initialisatiepatroon tijd bespaart of de initialisatie van de klasse duidelijker maakt.

Gemakinitializers worden in dezelfde stijl geschreven, maar met de modifier voor gemak geplaatst vóór het init-sleutelwoord, gescheiden door een spatie:

gemak init (_parameters indien aanwezig_) {
}

Laten we een voorbeeld bekijken: de menselijke klasse heeft één aangewezen init-methode en één gemakkelijke init-methode.

class HumanBeing {
var name: String
init (name: String) {
self.name = naam
}
gemak init () {
self.init (naam: "niet ingesteld")
// Gemak init roept de aangewezen init-methode aan
}
}
let humanBeingObj1 = HumanBeing () // roept gemak init aan
let humanBeingObj2 = HumanBeing (naam: "abhilash") // roept aangewezen init aan
Gemak init initialiseert de aangewezen init-methode door self.init aan te roepen.

Initialisatie delegatie voor klassen

Om de relaties tussen aangewezen en gemak-initializers te vereenvoudigen, past Swift de volgende drie regels toe voor delegatie-oproepen tussen initializers:

  • Een aangewezen initializer moet een aangewezen initializer uit zijn onmiddellijke superklasse oproepen. Een aangewezen initializer van een subklasse kan geen Convenience-init vanuit zijn superklasse oproepen. Als u dit probeert, krijgt u de foutmelding "error: moet een aangewezen initialisatie van de superklasse bellen".
  • Een gemakkelijke initialisatie moet een andere initialisatie uit dezelfde klasse aanroepen.
  • Een gemakkelijke initialisatie moet uiteindelijk een aangewezen initialisatie oproepen.

Bekijk de volgende afbeelding zodat deze duidelijker wordt:

bron: apple docs

Overname van automatische initialisatie

Subklassen erven niet standaard hun superklasse-initializers. Superklasse-initializers worden echter automatisch overgenomen als aan bepaalde voorwaarden is voldaan.

Als we standaardwaarden bieden voor nieuwe eigenschappen die u in een subklasse invoert, zijn de volgende twee regels van toepassing:

  • Regel 1: Als uw subklasse geen aangewezen initializers definieert, neemt deze automatisch alle aangewezen initialen van de superklasse over.
  • Regel 2: Als uw subklasse een implementatie biedt van alle initialen die door Superclass zijn aangewezen - door ze te erven volgens regel 1 of door een aangepaste implementatie te bieden als onderdeel van de definitie - dan neemt deze automatisch alle initialen van het superklassegemak over.

Beschouw het volgende voorbeeld en de beschikbare init-methoden om een ​​Man-klasseobject te maken.

class HumanBeing {
var name: String
init (name: String) {
self.name = naam
}
gemak init () {
self.init (naam: "niet ingesteld")
// Gemak init roept de aangewezen init-methode aan
}
}
let humanBeingObj1 = HumanBeing () // roept gemak init aan
let humanBeingObj2 = HumanBeing (naam: "abhilash") // roept
aangewezen init
____________________
class Man: HumanBeing {
var leeftijd: Int = 0
vervang init (name: String) {
super.init (naam: naam)
}
init (name: String, age: Int) {
super.init (naam: naam)
self.name = naam
self.age = leeftijd
}
}
_______________________
let manObj1 = Man () // roept convenience init van Human class aan
let manObj2 = Man (naam: “Robert”) // roept overriden init op
let manObj3 = Man (naam: “John”, leeftijd: 10) // roept custom init aan
manObj1.name // print “niet ingesteld”
manObj2.name // print “Robert”
manObj3.name // print “John”

Waar te gaan vanaf hier:

Initializers in snel deel-2: Beschikbare initializers in snel

Als je het leuk vond om dit bericht te lezen en het nuttig vond, deel het dan en raad het aan zodat anderen het kunnen vinden !!!!

Bedankt!!