Swift learning "SWIFT programming Tour---attributes (14)

Source: Internet
Author: User
Tags custom name

Property associates a value for a particular class, struct, or enumeration, and the storage property stores the constants and variables as part of the instance, and the computed property is used to calculate a value without storing it. Computed properties can be used in classes, structs, and enumerations, and stored properties are used only for classes and struct bodies. Storage properties and computed properties are typically used for instances of a particular type, but properties can also be used directly on the type itself, which is called a type property. In addition, you can define a property monitor to observe changes in the value of a property to trigger a custom action. The property monitor can be added to a storage property or to a property inherited from a parent class.

  Stored Properties Store Property

A stored property can be a constant or variable, you can set a default value for a storage property, or you can set or modify the value of a stored property during construction, or even modify the value of a constant store property

struct Fixedlengthrange {     var  firstvalue:int     var0 3   6

An instance of Fixedlengthrange contains a variable store property named Firstvalue and a constant storage property named length. In the example above, length is assigned when the instance is created, because it is a constant storage property, so its value cannot be modified after that.

storage properties of a constant struct   
0 4 )// This range represents integers values 0, 1, 2, and 36// this would repo RT an error, even though firstvalue are a variable property

Because Rangeoffouritems is declared as a constant, even if firstvalue is a variable property, it can no longer be modified. This is because the struct (struct) belongs to the value type. When an instance of a value type is declared as a constant, all its properties are also constants. Classes that belong to reference types are different, and you can still modify the instance's variable properties after assigning an instance of a reference type to a constant.

  Deferred storage properties

A deferred store property is a property whose initial value is evaluated when it is first called. Use the Lazy keyword to declare a deferred storage property before the property declaration.

Note: The deferred storage attribute must be declared as a variable (using the var keyword) because the value of the property may not be available until the instance construction is complete. The constant property must have an initial value before the construction process is complete, and therefore cannot be declared as a deferred attribute.

Deferred properties are useful when the value of a property depends on an external factor that cannot be known before the end of the instance's construction process, or when the value of the property requires complex or large computations, it can be evaluated only when needed.
classDataimporter {/*Dataimporter is a class-to-import data from an external file.     The class is assumed-a non-trivial amount of time to initialize. */    varFileName ="Data.txt"    //The Dataimporter class would provide data importing functionality here} classDataManager {LazyvarImporter =Dataimporter ()vardata =[String] ()//The DataManager class would provide data management functionality here} let manager=DataManager () manager.data.append ("Some Data") Manager.data.append ("Some More Data")//The Dataimporter instance for the Importer property had not yet been created

The DataManager class contains a storage property named data, and the initial value is an empty string array. The purpose of the DataManager class is to manage and provide access to this array of strings.

One feature of DataManager is the ability to import data from a file, which is provided by the Dataimporter class, and Dataimporter takes time to complete initialization: Because its instance might open a file at initialization time, it also reads the contents of the file into memory. DataManager may also not import data from the file. So when an instance of DataManager is created, it is not necessary to create an instance of Dataimporter immediately, and to create it when Dataimporter is used.

      

  Calculated properties

The computed property does not store the value directly, but instead provides a getter to get the value, an optional setter to indirectly set the value of the other property or variable.

structPoint {varx =0.0, y =0.0 } structSize {varwidth =0.0, height =0.0 } structRect {varOrigin =Point ()varSize =Size ()varCenter:point {Get{Let CenterX= origin.x + (Size.width/2) Let CenterY= ORIGIN.Y + (Size.Height/2)         returnPoint (X:centerx, Y:centery)}Set(newcenter) {origin.x= Newcenter.x-(Size.width/2) ORIGIN.Y= Newcenter.y-(Size.Height/2)     }     } } varSquare = Rect (Origin:point (x:0.0Y:0.0), Size:size (width:10.0, Height:10.0)) Let Initialsquarecenter=Square.center Square.center= Point (x:15.0Y:15.0) println ("Square.origin is now at (\ (square.origin.x), \ (SQUARE.ORIGIN.Y))") //output "Square.origin is today at (10.0, 10.0)"

The above defines the structure of 3 geometric shapes

The point encapsulates a coordinate (x, y)

The size encapsulates a width and heightrect that represents a rectangle with an origin and a size.

Rect also provides a computed property called center. The center point of a rectangle can be calculated from the origin and dimension, so it is not necessary to save it as an explicitly declared point. The computed properties of Rect Center provides a custom getter and setter to get and set the center point of the rectangle as if it had a stored property.

The example next creates a rect instance named Square, where the initial value is (0, 0) and the width height is 10. Blue Squares. The center property of Square can be accessed through the dot operator (Square.center), which invokes the getter to get the value of the property. Instead of returning a value that already exists directly, the getter actually calculates and returns a new point to represent the center of the square. As the code shows, it correctly returns the center point (5, 5). The Center property is then set to a new value (15, 15), which represents the position of moving the square to the Orange square to the right. Setting the value of the property center invokes the setter to modify the values of the X and Y properties of origin, thereby moving the square to a new position.

  Simple Setter Declaration

If the setter for the computed property does not define a parameter name that represents the new value, you can use the default name NewValue. The following is a rect struct code that uses the handy setter declaration:

structAlternativerect {varOrigin =Point ()varSize =Size ()varCenter:point {Get{Let CenterX= origin.x + (Size.width/2) Let CenterY= ORIGIN.Y + (Size.Height/2)         returnPoint (X:centerx, Y:centery)}Set{origin.x= newvalue.x-(Size.width/2) ORIGIN.Y= Newvalue.y-(Size.Height/2)     }     } } 

  Read-only computed properties

Only a getter without a setter is a computed property that is a read-only computed property. A read-only computed property always returns a value that can be accessed through the point operator, but cannot set a new value. The declaration of a read-only computed property can be stripped of the Get keyword and braces

structCuboid {varwidth =0.0, height =0.0, depth =0.0     varvolume:double {returnWidth * Height *Depth}} Let Fourbyfivebytwo= Cuboid (width:4.0, Height:5.0, Depth:2.0) println ("The volume of Fourbyfivebytwo is \ (fourbyfivebytwo.volume)") //output "The volume of Fourbyfivebytwo is 40.0"

  Attribute observation

Observe the change in property values and implement a custom action when a change occurs. You can add one or all of the following monitors for a property:

    • Willset called before the property value changes
    • Didset called immediately after the property value changes

The Willset monitor will pass in the new property value as a fixed parameter, you can specify a name for this parameter in the implementation code of the Willset, and if you do not specify the parameter is still available, the default name NewValue is used.

Similarly, the Didset monitor passes the old property values as parameters, either by naming the parameter or by using the default parameter name OldValue.

Note: Willset and Didset monitors are not called during property initialization, they are called only when the value of the property is set outside of the initialization.

classStepcounter {varTotalsteps:int =0{Willset (newtotalsteps) {print ("About -to-set totalsteps to \ (newtotalsteps)")} didset {ifTotalsteps >oldValue {print ("Added \ (totalsteps-oldvalue) steps")}}}}let Stepcounter=stepcounter () stepcounter.totalsteps= $//About-to- set totalsteps to//Added StepsStepcounter.totalsteps = the//About-to- set totalsteps to//Added StepsStepcounter.totalsteps =896//About-to- set Totalsteps to 896//Added 536 Steps

The Stepcounter class defines an int type property totalsteps, which is a storage property that contains Willset and Didset monitors.

When Totalsteps sets a new value, its willset and didset monitors are called, even when the new value is exactly the same as the current value. The Willset monitor in the example customizes the parameter representing the new value to Newtotalsteps, which simply outputs the new value. The Didset Monitor is called after the value of totalsteps is changed, comparing the new value to the old value, and if the total number of steps increases, the output of a message indicates how many steps are added. Didset does not provide a custom name, so the default value oldvalue represents the parameter name of the old value.

Note: If you assign a value to a property in the Didset monitor, this value replaces the value set before the monitor.

  Type property

Instance properties are properties that belong to instances of a particular type. Each time a new instance of the type is created, it has its own set of property values, detached from any other instance, and can also define properties for the type itself, with only one copy, regardless of the number of instances of the type. This property is the type attribute.

Type properties are used to define data shared by all instances of a particular type, such as a constant that all instances can use (just like a static constant in C), or a variable that all instances can access (just like a static variable in the C language). For value types (refers to structs and enumerations) you can define both the storage type and the computed Type property, and for the class, only the computed Type property. A stored Type property of a value type can be a variable or constant, and a computed type property is defined as a variable property as the computed property of an instance. Note: Unlike the storage properties of an instance, you must specify a default value for the stored Type property, because the type itself cannot use the constructor to assign a value to the Type property during initialization.

 

  Type attribute syntax

Use the keyword static to define the Type property of a value type, and the keyword class to define the Type property for the class. The following example shows the syntax for storage and computed type properties

structSomestructure {Static varStoredtypeproperty ="Some value."     Static varComputedtypeproperty:int {//This returns an INT value    } } enumsomeenumeration {Static varStoredtypeproperty ="Some value."     Static varComputedtypeproperty:int {//This returns an INT value    } } classSomeClass {class varComputedtypeproperty:int {//This returns an INT value    } } 

  Gets and sets the value of the Type property

instance, the access to the Type property is also done through the dot operator, but the Type property is obtained and set through the type itself, not through the instance. Like what

 //"Another   value. " //

The following example defines a struct that uses two storage type attributes to represent the sound level values of multiple channels, with an integer between 0 and 10 representing the sound level value for each channel.

The following diagram shows how to use two channels together to represent a stereo sound level value. When the level value of the channel is 0, no light is lit; when the channel level is 10, all lights are lit. In this figure, the left channel level is 9 and the right channel level is 7.

structAudiochannel {StaticLet Thresholdlevel =Ten     Static varMaxinputlevelforallchannels =0     varCurrentlevel:int =0{didset {ifCurrentLevel >Audiochannel.thresholdlevel {//set the new level value to the thresholdCurrentLevel =Audiochannel.thresholdlevel}ifCurrentLevel >Audiochannel.maxinputlevelforallchannels {//stores the current level value as the new maximum input levelAudiochannel.maxinputlevelforallchannels =CurrentLevel}} } } 

The structure Audiochannel defines 2 storage type attributes to achieve these functions. The first is Thresholdlevel, which represents the maximum upper threshold of the sound level, which is a constant value of 10, visible to all instances, and a maximum upper value of 10 if the sound level is above 10 (described later).

The second type attribute is the variable-stored-type attribute maxinputlevelforallchannels, which is used to represent the maximum value of the level value of all Audiochannel instances, with an initial value of 0. Audiochannel also defines an instance store property named CurrentLevel, which represents the current level value of the channel, with a value of 0 to 10. The CurrentLevel property contains the Didset property monitor to check the value of the property after each new setting, with the following two checks: If the new value of CurrentLevel is greater than the allowable threshold Thresholdlevel, The property monitor restricts the value of currentlevel to a threshold of thresholdlevel. If the corrected CurrentLevel value is greater than any previous value in any Audiochannel instance, the property monitor saves the new value in the static property maxinputlevelforallchannels. Note: During the first check, the Didset property monitor sets CurrentLevel to a different value, but the property monitor is not called again. You can use the struct Audiochannel to create two channels Leftchannel and rightchannel that represent a stereo system:
var leftchannel =var

If you set the level of the left channel to 7, the type attribute maxinputlevelforallchannels will also be updated to 7:

7//

If you attempt to set the level of the right channel to 11, the currentlevel of the right channel is corrected to the maximum value of 10, and the Maxinputlevelforallchannels value is updated to 10:

 One   println (rightchannel.currentlevel)  //  Output "Ten"  println ( Audiochannel.maxinputlevelforallchannels)  

Swift learning "SWIFT programming Tour---attributes (14)

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.