Inheritance and construction procedures for classes

Source: Internet
Author: User
Tags closure instance method
Inheritance and construction procedures for classesAll storage properties within a class-including all attributes inherited from the parent class-must set the initial value during the construction process.

Swift provides two types of class constructors to ensure that stored-type properties in all class instances get the initial values, respectively, for the specified constructor and the convenience builder.
specifying constructors and convenience constructorsSpecifies that the constructor is the most important constructor in the class. A specified constructor initializes all the properties provided in the class and implements the initialization of the parent class based on the constructor of the parent class that is called on the parent class chain.

Each class must have at least one specified constructor. In some cases, many classes satisfy this condition by inheriting the specified constructor in the parent class. For details, refer to the successor of the automatic constructor for the following chapters.

The convenience builder is a secondary, auxiliary type constructor in a class. You can define a convenience constructor to invoke the specified constructor in the same class and provide default values for its arguments. You can also define a convenience builder to create an instance of a special purpose or specific input.

You should only provide a convenient constructor for the class when necessary, for example, in some cases, by using the convenience constructor to invoke a specified constructor quickly, saving more development time and making the class process clearer and more clear.
constructor ChainTo simplify the invocation relationship between the specified constructor and the convenience constructor, Swift uses the following three rules to restrict proxy calls between constructors: Specifies that the constructor must call the specified constructor of its immediate parent class. The convenience builder must call other constructors defined in the same class. The convenience builder must end with a call to a specified constructor.
A more convenient way to remember is to:
Specifies that the constructor must always be up-agent convenient constructors must always be horizontal agents these rules can be illustrated by the following illustration:


As shown in the figure, the parent class contains a specified constructor and two convenience constructors. One of the convenience constructors calls another convenience constructor, and the latter invokes a unique specified constructor. This satisfies the above mentioned rules 2 and 3. This parent class does not have its own parent class, so rule 1 is not used.

The subclass contains two specified constructors and a convenience builder. The convenience builder must call any of the two specified constructors because it can only invoke other constructors in the same class. This satisfies the above mentioned rules 2 and 3. The two specified constructors must invoke the only specified constructor in the parent class, which satisfies rule 1.
Note: These rules do not affect how you create an instance with a class when you use it. Any of the constructors shown in the above illustration can be used to create an instance of the corresponding class completely. These rules affect only when the definition of a class is implemented. A more complex class-level structure is shown in the following illustration. It demonstrates that specifying a constructor simplifies the internal relationship between classes on the constructor chain of a class if it acts as a "pipe" in the class hierarchy.

Two-stage construction processThe construction of classes in Swift consists of two phases. In the first phase, each storage-type property sets the initial value by introducing the constructor of their class. When each storage-type attribute value is determined, the second stage begins, giving each class an opportunity to further customize their storage properties before the new instance is ready for use.
The use of the two-stage construction process makes the construction process more secure, while giving each class complete flexibility throughout the class hierarchy. The two-stage construction process prevents property values from being accessed before initialization, or prevents a property from accidentally assigning a different value to another constructor.
Note: Swift's two-part construction process is similar to the construction process in objective-c. The main difference is that the stage 1,objective-c assigns a value of 0 or null to each attribute (for example, 0 or nil). Swift's construction process is more flexible, allowing you to set custom initial values and be comfortable with certain properties that cannot be used as a valid default value of 0 or nil. The Swift compiler performs 4 valid security checks to ensure that the two-stage construction process is completed successfully: The specified constructor must ensure that all attributes introduced by the class in which it resides must be initialized before the other constructed tasks are represented up to the constructor in the parent class. As noted above, the memory of an object can be fully initialized only after all its storage-type attributes are determined. To satisfy this rule, the specified constructor must ensure that the attribute introduced by its class completes initialization before it is proxied. Specifies that the constructor must first invoke the parent class constructor, and then set the new value for the inherited property. If this is not done, the new value given by the specified constructor will be overwritten by the constructor in the parent class. The convenience builder must first invoke the other constructors in the same class, and then assign a new value to any property. If this is not done, the new values given by the convenience constructor will be overwritten by other specified constructors in the same class. The constructor cannot invoke any instance method, read the value of any instance property, or reference the value of self until the first stage construction completes.
The following is a demonstration of the construction process based on the above security checks in the two-stage construction process:

Phase 1:
A specified constructor or convenience constructor is invoked, the new instance memory is allocated, but the memory is not initialized at this time, and the specified constructor ensures that all storage attributes introduced by the class in which it resides are assigned an initial value. The memory that the storage property belongs to completes initialization; Specifies that the constructor will invoke the constructor of the parent class to complete the initialization of the parent class property, and that the process of invoking the parent constructor is carried up along the constructor chain until it reaches the top of the constructor chain, and when it reaches the top of the constructor chain, and has ensured that all instances contain stored-type attributes that have been assigned values, and that the memory of this instance is considered fully initialized. At this stage 1 completes.
Phase 2:
From the top constructor chain down, the specified constructor for the class in each constructor chain has the opportunity to further customize the instance. The constructor can now access self, modify its properties, invoke instance methods, and so on. Finally, a convenience constructor in any constructor chain can have the opportunity to customize the instance and use self.
The following figure shows the stages that are constructed between the hypothetical subclass and the parent class 1:


In this example, the construction process begins with a call to a convenient constructor in the subclass. This convenience constructor cannot modify any properties at this time, and it proxies the constructor task to the specified constructor in the same class.

As security check 1 shows, the specified constructor will ensure that the properties of all subclasses have a value. It then invokes the specified constructor of the parent class and completes the build process of the parent class along the chain of the builders.

The specified constructor in the parent class ensures that all properties of the parent class have a value. Since no more parent classes need to be built, there is no need to continue building the agent up.

Once all the properties in the parent class have an initial value, the memory of the instance is considered to be fully initialized, and Phase 1 is completed.

Phase 2 of the same construction process is shown below:


The specified constructor in the parent class now has the opportunity to further customize the instance (although it is not necessary).

Once the specified constructor in the parent class completes the call, the constructor of the subclass specifies that the builder can perform more custom operations (nor is it necessary).

Finally, once a subclass's specified constructor completes the invocation, the convenience constructor that is first invoked can perform more custom operations.
constructors ' inheritance and overloadUnlike subclasses in Objective-c, a subclass in Swift does not inherit the parent class's constructor by default. This mechanism of Swift prevents a simple constructor of a parent class from being inherited by a more professional subclass and incorrectly used to create instances of subclasses.

If you want to implement one or more constructors that are the same as the parent class in a custom subclass-perhaps to complete some custom construction process-you can provide and overload the same constructor as the parent in your custom subclass.

If you overload the constructor with a specified constructor, you can overload its implementation in the subclass and invoke the parent-class version of the constructor in the custom version of the constructor.

If your overloaded constructor is a convenience constructor, your overloaded procedure must be implemented by invoking other specified constructors provided in the same class. Refer to the constructor chain for details of this rule.
Note: Unlike methods, properties, and subscripts, you do not need to use the keyword override when overloading the constructor. inheritance of automatic constructorsAs mentioned above, subclasses do not inherit the constructors of the parent class by default. However, if certain conditions are satisfied, the parent class constructor can be inherited automatically. In practice, this means that you do not have to overload the constructor of the parent class for many common scenarios and inherit the constructor of the parent class at the lowest cost, if possible.
If you want to provide a default value for any new properties introduced in a subclass, observe the following 2 rules: If a subclass does not define any of the specified constructors, it automatically inherits the specified constructor for all the parent classes. If a subclass provides implementations of all parent classes that specify constructors-either inherited through Rule 1 or implemented by custom-it automatically inherits the convenience builder of all parent classes.
Even if you add more convenience constructors to the subclass, these two rules still apply.
Note: Subclasses can use the subclass convenience constructor to implement the specified constructor of the parent class by partially satisfying rule 2. specifying the syntax of constructors and convenience constructorsThe specified constructor for a class is written like a simple constructor for a value type:
The init (parameters) {statements} Convenience Builder also uses the same style, but you need to place the convenience keyword before the init keyword and separate them with a space:
Convenience init (Parameters) {statements} specifying constructors and facilitating constructors combatThe next example will show the inheritance of the specified constructor, convenience builder, and automatic constructor in actual combat. It defines class hierarchies that contain three classes of food, recipeingredient, and Shoppinglistitem, and will demonstrate how their constructors interact.

The base class in the class hierarchy is food, which is a simple class for encapsulating food names. The food class introduces a string attribute called name, and provides two constructors to create an food instance:
Class Food {var name:string init (name:string) {self.name = name} convenience init () {self.init (name: [Unnamed])} The food constructor chain is shown in the following figure:


Class does not provide a default one-member constructor, the food class provides a specified constructor that accepts a single parameter name. This constructor can use a specific name to create a new food instance:
Let namedmeat = Food (name: "Bacon")//Namedmeat is named "Bacon" the constructor init (Food) in the Name:string class is defined as a specified constructor. Because it ensures that all of the new food instances are initialized with the stored-type attributes. The food class does not have a parent class, so the Init (name:string) constructor does not need to invoke Super.init () to complete the construct.

The food class also provides a convenient constructor init () with no parameters. This init () constructor provides a default placeholder name for new food and is implemented by proxy calling the specified constructor init (name:string) defined in the same class and passing value [unnamed] to the parameter name:
Let mysterymeat = Food ()//Mysterymeat's name is the second class in the [unnamed] class hierarchy, which is the Food subclass Recipeingredient. The Recipeingredient class builds a recipe for flavoring. It introduces the number attribute quantity (and the name attribute inherited from food) of type int, and two constructors are defined to create the Recipeingredient instance:
Class Recipeingredient:food {var quantity:int init (name:string, quantity:int) {self.quantity = Quantity Super.init (n Ame:name)} convenience init (name:string) {self.init (Name:name, Quantity:1)}} The following figure shows the constructor chain for the Recipeingredient class:


The Recipeingredient class has a specified constructor init (name:string, quantity:int) that can be used to generate all the property values for the new Recipeingredient instance. The constructor first assigns the passed-in quantity parameter to the Quantity property, which is the only new attribute that is introduced in Recipeingredient. The constructor then proxies the task up to the Food init (name:string) of the parent class. This process satisfies the security 1 of the two-stage construction process.

Recipeingredient also defines a convenient constructor init (name:string), which creates instances of Recipeingredient only through name. This convenience builder assumes that the quantity of any recipeingredient instance is 1, so you do not need to display a specified number to create an instance. This convenience builder definition makes it easier and faster to create instances, and avoids the use of duplicate code to create multiple Recipeingredient instances with quantity 1. This convenience builder simply gives the task an agent to the specified constructor provided in the same class.

Note that the Recipeingredient Convenience builder init (name:string) uses the same parameters as the specified constructor init (name:string) in food. Although Recipeingredient is a convenient constructor, Recipeingredient still provides implementations of the constructor specified for all parent classes. Therefore, recipeingredient can also automatically inherit the convenience builder of all parent classes.

In this example, the Recipeingredient parent class is food, which has a convenient constructor init (). This constructor is therefore also recipeingredient inherited. This inherited init () function version is the same as the version provided by food, except that it is a version of the task that is being delegated to recipeingredient version of Init (name:string) instead of food.

All three constructors can be used to create a new Recipeingredient instance:
Let-Onemysteryitem = Recipeingredient () let-Onebacon = recipeingredient (name: "Bacon") Let Sixeggs = recipeingredient (name : The third and final class in the class hierarchy of "Eggs", Quantity:6) is the Recipeingredient subclass, called Shoppinglistitem. This class builds one of the seasonings that appears in the shopping list.

Each item in the shopping list is always started from the unpurchased state. To demonstrate this fact, Shoppinglistitem introduces a Boolean-type property purchased, whose default value is False. Shoppinglistitem also adds a computed attribute description, which provides some textual descriptions of the Shoppinglistitem instance:
Class Shoppinglistitem:recipeingredient {
    var purchased = False
    var description:string {
    var output = ' \ (qua ntity) x \ (name.lowercasestring) "
        output = = purchased?" "✔": "✘" return
        output
    }
}
Note: Shoppinglistitem does not have a constructor defined to provide the initialization value for purchased because the initial state of any item added to the shopping list is always not purchased. Because it provides default values for all of the properties that it introduces and does not define any constructors itself, Shoppinglistitem automatically inherits the specified constructor and the convenience builder in all the parent classes.

The following illustration shows the constructor chains for all three classes:


You can use all three inherited constructors to create a new instance of Shoppinglistitem:
var breakfastlist = [Shoppinglistitem (), Shoppinglistitem (name: "Bacon"), Shoppinglistitem (name: "Eggs", Quantity:6),] Breakfastlist[0].name = "Orange Juice" breakfastlist[0].purchased = True for item in Breakfastlist {println (Item.descrip tion)}//1 x Orange juice✔//1 x bacon✘//6 x Eggs✘ as described above, a new array breakfastlist is created by literal means in the example, which contains three new Shoppinglistitem instances , so the type of the array can also be automatically deduced as shoppinglistitem[]. After the array is created, the name of the first Shoppinglistitem instance in the array is modified from [unnamed] to orange juice and marked as purchased. Next, by traversing each element of the array and printing their descriptive values, the current default state of all items is shown to have been assigned as expected.
setting default values for properties by closures and functionsIf the default value of a storage attribute requires special customization or preparation, you can use closures or global functions to provide custom defaults for its properties. Whenever a new type instance to which a property belongs is created, the corresponding closure or function is invoked, and their return value is assigned to this property as the default value.

This type of closure or function typically creates a temporary variable that is the same as the property type and then modifies its value to meet the expected initial state, and finally returns the value of the temporary variable as the default value of the property.

The following is a summary of the code for how closures provide default values:
Class SomeClass {Let Someproperty:sometype = {//Create a default value for Someproperty in this closure//somevalue must be the same as the SomeType type return som Evalue} ()} Note that the curly brace at the end of the closure is followed by a pair of empty parentheses. This is used to tell Swift to execute this closure immediately. If you omit this pair of parentheses, you assign the closure itself as a value to the property, rather than assigning the return value of the closure to the property.
Note: If you use closures to initialize the value of a property, remember that the rest of the instance is not initialized when the closure is executed. This means that you are not able to access other properties in the closure, even if the attribute has a default value that is not allowed. Similarly, you cannot use the implicit self attribute, or invoke other instance methods. The following example defines a struct checkerboard, which constructs the chessboard of the Checkers game:


The Checkers game is played in an alternating black and white chessboard of 10x10. To render the game board, the checkerboard structure defines a property boardcolors, which is an array of 100 Boolean values. An element in an array with a Boolean value of TRUE indicates a black grid, and a Boolean value of False indicates a white lattice. The first element in the array represents the upper-left corner of the chessboard, and the last element represents the lattice on the lower-right corner of the chessboard.

The Boardcolor array initializes and assembles the color values through a closure:
struct Checkerboard {let boardcolors:bool[] = {var temporaryboard = bool[] () var isblack = False to I in 1...10 {for J in 1...10 {temporaryboard.append (isblack) isblack =!isblack} isblack =!isblack} return Temporaryboard} () func Squa Reisblackatrow (Row:int, column:int)-> Bool {return boardcolors[(row *) + column]}} whenever a new checkerboard instance is created, the corresponding The assignment closure executes, and a series of color values are computed as the default values assigned to Boardcolors. The closure described in the above example calculates the appropriate color for each lattice in the chessboard, saves the color values to a temporary array temporaryboard, and returns the array as the closure return value when the build completes. The returned value is saved to the boardcolors and can be queried by squareisblackatrow this tool function.
Let board = CHEC

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.