Swift Learning Notes (vii)

Source: Internet
Author: User
Tags closure instance method

14 Initialization

Initialization is the preparation phase of the instantiation of classes, structs, and enumeration types. This stage sets the initialization values for the properties stored by this instance and makes some preparations before using the instance and some other setup work that must be done.

This instantiation process is implemented by defining the constructor (initializers), which is a special method of creating a new concrete instance. Unlike Objective-c,Swift's constructor does not return a value. Their primary role is to ensure that the instance is properly initialized before it is used.

Class instances can also implement a destructor (Deinitializer) to do some cleanup before the class instance is destroyed.

1. Initialization of storage properties

Classes and structs must set all their properties to a reasonable value when they are created. The storage property cannot be in an indeterminate state

You can set an initial value for a property in the constructor, or set a default value for the property at the time of definition.

Note: When you assign a default value to a property, it calls its corresponding initialization method, which is set directly on the property and does not notify its corresponding observer

Constructors

A constructor is a method that creates an instance of a concrete type. The simplest constructor is a method that does not have any argument instances, writing init.

In the following example , a new structure called Fahrenheit (Fahrenheit) is defined to store the temperature of the converted Chenghua. Fahrenheit structure, which has an attribute called temperature (temperature), is of type double (double-precision floating-point number):

struct Fahrenheit {    var temperature:double    init () {        temperature = 32.0    }}var f = Fahrenheit () print ("The Default temperature is \ (f.temperature) °fahrenheit ")

This struct defines a single constructor init, which does not have any parameters, and its stored temperature attribute is initialized to 32 degrees. (The freezing point of water at the temperature of Fahrenheit).

Default value of the property

As mentioned above, you can set the initialization value of its own storage property in the constructor. Or, in the case of a property declaration, specify the default value of the property, and you specify a default property value that will be assigned to the initial value it defines.

Note: If an attribute often uses the same initialization value , providing a default value would be better than using a default value in initialization.

The same result, but the default value and the initialization of the property are tightly bound together when it is defined. It is simple to be able to make the constructor more concise, and allows you to infer the type of the property from the default value.

struct Fahrenheit1 {    var temperature = 32.0}

2. Custom initialization (customizing initialization)

You can customize the initialization process and optional property types based on the input parameters, or modify the static properties at initialization time.

Initialize parameters

You can provide a subset of parameters when the constructor is defined, defining the type and name of the variable during the custom initialization process.

Initialization parameters have the same function as functions or method parameters.

In the following example, a structural body Celsius is defined . Storing the temperature converted to Celsius, theCelsius structure implements two methods for initializing the structure from different temperatures,init (Fromfahrenheit:) and Init (Fromkelvin:).

struct Celsius {    var temperatureincelsius:double = 0.0    init (Fromfahrenheit fahrenheit:double) {        Temperatureincelsius = (fahrenheit-32.0)/1.8    }    init (Fromkelvin kelvin:double) {        Temperatureincelsius = k elvin-273.15    }}let boilingpointofwater = Celsius (fromfahrenheit:212.0) Let Freezingpointofwater = Celsius ( fromkelvin:273.15)

The first constructor has only one initialization parameter, the formal parameter (External Parameter Names) Fromfahrenheit, and the actual argument (Local Parameter Names) Fahrenheit. The second constructor has a single initialization parameter, the formal parameter (External Parameter Names) Fromkenvin, and the actual parameter (Local Parameter Names) Kelvin. Each of the two constructors converts a single parameter to Celsius and stores it to a Temperatureincelsius attribute.

Argument name (Local Parameter Names) and formal parameter name (External Parameter Names)

As with function parameters and method parameters, the initialization parameters have arguments that are used in the constructor function body, and that are used at the time of invocation .

However, unlike functions or methods, the constructor does not have a recognized function name in front of the parentheses. Therefore, the name and type of the constructor parameter, when called, plays a significant role in recognition. To do this, in the constructor, when you do not provide a formal parameter name,Swift provides an automatic formal parameter name for each parameter. The formal parameter name is the same as the argument name, just like the hash symbol for each initialization parameter you wrote earlier .

Note: If you do not have a formal parameter defined in the constructor, provide a lower horizontal line (_) as the overriding default behavior that distinguishes the formal parameter and the above described.

In the following example , a struct Color is defined, with three static properties red, green,and blue. These properties store values from 0.0 to 1.0, which represent the depth of red, green, and blue.

Color provides a constructor, as well as three double-type parameters:

struct Color {    var red = 0.0, green = 0.0, blue = 0.0    init (red:double, green:double, blue:double) {        self.re D   = red        self.green = Green        self.blue  = Blue    }}

Whenever you create a color instance, you must call the constructor with the formal parameters of each color:

Let magenta = Color (red:1.0, green:0.0, blue:1.0)

Optional type

If you store properties using a custom type that logically allows values to be null -or their values are not initialized in the constructor, or they are allowed to be empty. You can define an attribute of an optional type. The optional type attribute is an auto-initialize value of nil, which indicates that this property is intentionally set to "null " (no valueyet) in the constructor.

In the following example, a Surveryquestion class is defined, with an optional string attribute of response.

This answer is not known until they investigate the issue before it is released, so response is defined as a type string, or an optional string (Optional String). Indicates that it is automatically assigned a default value of nil, meaning that it does not exist when Surverquestion is initialized.

modifying static properties at initialization time

When you set a static property value, you can modify the static property at any time during initialization, as long as the initialization is complete.

Note: For instantiation of a class, a static property can only be modified at initialization time, which is determined at the time of class definition.

You can override the surveryquestion example, and for the Text property of the problem , using a static property is better than a dynamic property because the Surveyquestion instance cannot be modified after it is created. Although the Text property is now static, it can still be set in the constructor:

Class Surveyquestion {let    text:string    var response:string?    Init (text:string) {        self.text = text    }    func Ask () {        print (text)    }}let beetsquestion = Surveyquestion (text: "How about beets?") Beetsquestion.ask () Beetsquestion.response = "I also like beets. (but not with cheese.) "

3. Default constructor

Swift provides a default constructor for each struct or base class to initialize all of the properties that they contain. The default constructor creates a new instance and then sets their properties to the default values.

The following example defines a class called Shoppinglistitem that contains the name, the number, and whether the property has been purchased, and will be used in the shopping list:

Class Shoppinglistitem {    var name:string?    var quantity = 1    var purchased = False}var item = Shoppinglistitem ()

Because all properties in the Shoppinglistitem class have default values, and the class is a base class that does not have a parent class, it defaults to a default constructor that sets all contained properties to their initial values. For example, in this example , the Name property is an optional string property, which is set to nil by default, although it is not specified in the code. The example above uses the default constructor to create a Shoppinglistitem class, remember to do Shoppinglistitem (), and assign it to the variable item.

struct-type member-by-constructor

In addition to the default constructors mentioned above, there is another constructor for the struct type that initializes each member, specifying the initial value of each property directly when defining the structure.

Member-by-constructor is an easy way to initialize the member properties of a struct. The following example defines a structure called size, and two attributes are called width and height, respectively . Each property is of type double and initialized to 0.0.

Because each storage property has a default value, This member-by-constructor Init (width:height:) can be called automatically when an instance of the size structure is created:

struct Size {    var width = 0.0, height = 0.0}let twobytwo = Size (width:2.0, height:2.0)

4. Constructor proxy for numeric type

During initialization of an instance, the constructor can invoke other constructors to complete the initialization. This process, called the constructor agent, avoids duplicate code for multiple constructors.

For numeric types and classes, the constructor agent does not work the same way. numeric types (structs and enumerations) do not support inheritance, so their constructor proxies are relatively straightforward because they can only use their own constructor proxies. But a class can inherit from another class, so the class needs to make sure that all of its stored properties are set to the correct values at initialization time.

For numeric types, you can use Self.init to invoke other constructors, and note that the corresponding constructor can only be called inside this numeric type.

It is important to note that if you define a constructor for a numeric type, you can no longer use the default constructor. This feature avoids errors when you provide a particularly complex constructor, and another person mistakenly uses the default constructor.

Note: If you want to use both the default constructor and the constructor you set yourself, do not write these two constructors together, but instead use the extended form.

The following example defines a struct rect to represent a rectangle in a geometry. This RECT structure requires two additional structures, including size and point, and the initial value is 0.0:

struct Point {    var x = 0.0, y = 0.0}

Now you have three ways to initialize the RECT structure: directly using the 0 values initialized for the origin and Size properties , given a specified origin and size , or initialized with a center point and sizing. The following examples contain these three types of initialization:

struct Rect {    var origin = point ()    var size = size ()    init () {}    init (Origin:point, size:size) {self        . Origin = origin        self.size = size    }    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) 
   
    }}
   

5. Inheritance and initialization of classes

The custom initialization method calls its own class default initialization method, overriding the default initialization method to call the parent class default initialization method first

The constructor of the parent class or its own default constructor should be called first to prevent the property from being assigned a value before calling the parent class or its own default constructor to overwrite the previous assignment.

6. Set a default property value by a closure or function

If the default value of the stored property requires additional special settings, it can be done using closures or functions.

The closure or function creates a temporary variable to assign to the property as the return value. Here is a schematic code that uses a closure assignment:

Class SomeClass {let    someproperty:sometype = {        //Create a default value for Someproperty inside this Closure
   //Somevalue must be of the same type as SomeType        return somevalue    } ()}

It is important to note that there are two parentheses at the end of the closure to tell Swift that the closure needs to be executed immediately.

Note: If you use closures to initialize a property, some of the subsequent properties are not initialized when the closure is executed. Do not access any of the following properties in the closure, an error occurs, and you cannot use the Self property, or another instance method.

The following example is a structure called Checkerboard , which is made by the game Checkers .

Image this game is done on a 10x10 black and white grid. To represent this game disk, using a structure called Checkerboard, where a property called Boardcolors, is an array of 100 bool types. True indicates that the lattice is black andfalse indicates white. Then the initialization can be initialized with the following code:

struct Checkerboard {Let    boardcolors: [bool] = {        var temporaryboard = [bool] ()        var isblack = False        for I in 1...10 {to            J in 1...10 {                temporaryboard.append (isblack)                isblack =!isblack            }            isblack =!i Sblack        }        return Temporaryboard    } ()    func squareisblackatrow (Row:int, column:int), Bool {        return boardcolors[(Row *) + column]    }}

When a new checkerboard instance is created, the closure executes, and then the default value of the Boardcolor is computed and returned, and then as a property of the structure. you can detect if it is set correctly by using the Squareisblackatrow tool function:

Let board = checkerboard () print (Board.squareisblackatrow (0, Column:1)) print (Board.squareisblackatrow (9, Column:9))

Analysis of the structure

Destructors are called before an instance of a class is freed. Use the keyword deinit to define the destructor, similar to the initialization function defined by init. Destructors are only available for class types.

1, the principle of the process of destruction

Swift frees up resources by automatically releasing instances that are no longer needed. As described in the Chapter automatic reference count,Swifthandles memory management of instances by automatic reference counting (ARC). Typically, you do not need to manually clean up your instances when they are released. However, when you use your own resources, you may need to do some extra cleanup. For example, if you create a custom class to open a file and write some data, you may need to close the file before the class instance is freed.

In the definition of a class, there can be at most one destructor per class. Destructors do not have any arguments, and are not written in parentheses:

Deinit {    //Perform the destruction process}

A destructor is called automatically before the instance release occurs. You are not allowed to invoke your own destructor actively. Subclasses inherit the destructor of the parent class, and at the end of the subclass destructor implementation, the parent class's destructor is automatically called. Destructors for a parent class are always called, even if the subclass does not provide its own destructor.

Because the instance is not freed until the instance's destructor is called, the destructor can access the properties of all the request instances, and it can modify its behavior based on those properties (such as finding a file name that needs to be closed).

2, the destructor operation

Here is an example of a destructor operation. This example is a simple game that defines two new types,bank and Player. The bank structure manages the flow of a virtual currency, in which the bank can never have more than 10,000 coins. There is only one bank in this game , so the bank is implemented by a struct with static attributes and static methods to store and manage its current state.

struct Bank {    static var Coinsinbank = 10_000    static func vendcoins (Var numberofcoinstovend:int), Int {        numberofcoinstovend = min (numberofcoinstovend, Coinsinbank)        Coinsinbank-= Numberofcoinstovend        return Numberofcoinstovend    }    static func Receivecoins (coins:int) {        Coinsinbank + = Coins    }}

Bank is based on its the Coinsinbank property to track the current number of coins it owns. The bank also provides two methods --vendcoins and receivecoins--to handle the distribution and collection of coins.

The Vendcoins method checks if there are enough coins before the bank distributes the coins. If there are not enough coins, thebank returns a number that is smaller than the request (returns 0 if no coin is left in the bank ). The Vendcoins method declares numberofcoinstovend as a variable argument so that the number can be modified inside the method body without having to define a new variable. The Vendcoins method returns an integer value indicating the actual number of coins provided.

The Receivecoins method simply adds the number of coins stored and received to the Bank and saves it back to the bank.

The player class describes a player in the game. Each player has a certain number of coins stored in their wallets at any one time. This is illustrated by the player's Coinsinpurse property:

Class Player {    var coinsinpurse:int    init (coins:int) {        coinsinpurse = bank.vendcoins (coins)    }    Func Wincoins (coins:int) {        coinsinpurse + bank.vendcoins (coins)    }    deinit {        print ("Quit")        Bank.receivecoins (Coinsinpurse)    }}

Each player instance is initialized with a specified number of coins, which are obtained during the bank initialization process. If there are not enough coins available, theplayer instance may receive fewer coins than the specified number.

The player class defines a Wincoins method that obtains a certain number of coins from the bank and adds them to the player's wallet. The player class also implements a destructor, which is called in the previous step of the player instance release. Here the destructor simply returns all the players ' coins to the bank:

var playerone:player? = Player (coins:100) print ("A new player has joined the game with \ (playerone!. Coinsinpurse) Coins ") print (" There is now \ (Bank.coinsinbank) coins left in the Bank ")

A new player instance is created with a request of 100 coins (if any). This player instance is stored in an optional player variable named Playerone . An optional variable is used here because the player can leave the game at any time. Set to optional so that you can track whether there are currently players in the game.

Because Playerone is optional, it is decorated by an exclamation point (!), and whenever its Wincoins method is called, theCoinsinpurse property is accessed and prints out its default number of coins.

playerone!. Wincoins (2_000) print ("Playerone won coins & now have \ (playerone!. Coinsinpurse) Coins ") Print (" The bank is only have \ (Bank.coinsinbank) coins left ")

Here, the player has won the 2,000 coin. the player's wallet now has 2,100 coins, and the bank has only 7,900 coins left.

Playerone = Nilprint ("The Bank now has \ (bank.coinsinbank) Coins")

The player has now left the game. This indicates that you want to set the optional playerone variable to nil, which means "There is no player instance ." When this happens, theplayerone variable's reference to the player instance is broken. There is no other property or variable that references the player instance, so it is freed in order to empty the memory it occupies. Before this occurs, its destructor is automatically called and its coins are returned to the bank.

Swift Learning Notes (vii)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.