Swift Programming Language -- Instance Methods and Type Methods)

Source: Internet
Author: User

Swift Programming Language -- Instance Methods and Type Methods)

The method is a function associated with certain types. You can define instance methods for classes, structs, and enumerations. instance methods encapsulate specific tasks and functions for a given type of instances. Class, struct, and enumeration can also define the type method. The type method is associated with the type itself. The type method is similar to the class methods in Objective-C.

Struct and enumeration can be defined as one of the main differences between Swift and C/Objective-C. In Objective-C, a class is the only type that can define a method. However, in Swift, you can choose not only to define a class/struct/enumeration, but also flexibly define methods on the type (Class/struct/enumeration) you create.

Instance method)

The instance method belongs to a specific class, struct, or enumeration type instance. The instance method provides methods for accessing and modifying instance attributes, or provides functions related to the instance's purpose, and supports the instance's functions. The syntax of the instance method is exactly the same as that of the function. For more information, see functions.

The instance method should be written between the braces of its type. The instance method can implicitly access all other instance methods and attributes of its type. An instance method can only be called by a specific instance of the class to which it belongs. The instance method cannot be called without the existing instance.

The following example defines a very simple Counter class. Counter can be used to count the number of times an action occurs:

class Counter {  varcount = 0 func increment() {   count++  } func incrementBy(amount: Int) {   count += amount  } func reset() {   count = 0  }}


The Counter class defines three instance methods:

Increment increments the counter by one;

IncrementBy (amount: Int) increments the counter by a specified integer;

The reset resets the counter to 0.

The Counter class also declares a variable attribute count, which is used to keep track of the current Counter value.

Like calling properties, call the instance method using dot syntax:

Letcounter = Counter () // The initial count value is 0 counter. increment () // The Count value is now 1 counter. incrementBy (5) // The Count value is now 6 counter. reset () // The Count value is now 0


Local and External Parameter Names for Methods)

A function parameter can have a local name (used inside the function body) and an external name (used when calling the function). For more information, see the External Parameter Name of the function. The same is true for method parameters (because the method is a function, but this function is associated with a type ). However, the default behavior of local names and external names of methods and functions is different.

Methods In Swift are very similar to those in Objective-C. Like in Objective-C, the method name in Swift usually points to the first parameter of the method, such as with, for, and. In the previous Counter class example, the incrementBy method is like this. The use of prepositions allows a method to be interpreted as a sentence when called. Unlike function parameters, Swift uses different default processing methods for method parameters, which makes it easier to write method naming rules.

Specifically, by default, Swift only gives the first parameter name of the method a local parameter name. By default, it also gives the second and subsequent parameter names a local parameter name and an external parameter name. This Convention is compatible with typical naming and calling conventions, and is very similar to when you write Objective-C methods. This Convention also removes the need to limit parameter names when calling Expression methods.

Take a look at another version of Counter below (it defines a more complex incrementBy method ):

class Counter {  varcount: Int = 0 func incrementBy(amount: Int, numberOfTimes: Int) {   count += amount * numberOfTimes  }}


The incrementBy method has two parameters: amount and numberOfTimes. By default, Swift only treats amount as a local name, But numberOfTimes as a local name and an external name. Call this method as follows:

let counter = Counter()counter.incrementBy(5, numberOfTimes: 3)// counter value is now 15


You do not need to define an external variable name for the first parameter value: because the function name incrementBy can clearly see its role. However, the second parameter must be limited by an external parameter name to define its role when the method is called.

This default action can be used as a valid method, similar to writing a pound sign (#) before the numberOfTimes parameter (#):

func incrementBy(amount: Int,#numberOfTimes: Int) { count += amount * numberOfTimes}


This default behavior makes the above Code mean that the method defined in Swift uses the same syntax style as Objective-C, and the method will be called as a natural expression.

Modifying External Parameter Name Behavior for Methods)

Sometimes it is very useful to provide an external parameter name for the first parameter of the method, although this is not the default behavior. You can add an explicit external name or use a # As the prefix of the first parameter to use this local name as an external name.

Instead, if you do not want to provide an external name for the second and subsequent parameters of the method, you can use the underscore (_) as the explicit external name of the parameter, this will overwrite the default behavior.

Self Property)

Each instance of the type has an implicit attribute called self, which is equivalent to the instance itself. You can use this implicit self attribute in an instance method to reference the current instance.

The increment method in the preceding example can also be written as follows:

func incrementBy(amount: Int,#numberOfTimes: Int) { count += amount * numberOfTimes}

In fact, you don't have to write self frequently in your code. Whenever a known attribute or method name is used in a method, if you do not explicitly write self, Swift assumes that you are the attribute or method of the current instance. This assumption has been demonstrated in the Counter above: count (rather than self. count) is used in all the three instance methods in Counter ).

The main scenario of using this rule is that a parameter name of the instance method is the same as an attribute name of the instance. In this case, parameter names have priority and must be referenced in a more rigorous manner. In this case, you can use the self attribute to distinguish between parameter names and attribute names.

In the following example, self eliminates ambiguity between method parameter x and instance property x:

Struct Point {varx = 0.0, y = 0.0 func isToTheRightOfX (x: Double)-> Bool {return self. x> x }}let somePoint = Point (x: 4.0, y: 5.0) if somePoint. isToTheRightOfX (1.0) {println ("This point is to the right of the line where x = 1.0 ")} // output "This pointis to the right of the line where x = 1.0" (This point is on the right of the line x equals 1.0)


If the self prefix is not used, Swift considers that the x used twice refers to the function parameter named x.

Modify the Value type (Modifying Value Types from Within Instance Methods) in the Instance method)

Struct and enumeration are value types. Generally, the attribute of the value type cannot be modified in its instance method.

However, if you really need to modify the struct or enumeration attributes in a specific method, you can choose mutating, then the method can change its attributes from inside the method, and any changes it makes will be kept in the original structure at the end of the method. The method can also assign a new instance to its hidden self attribute. The new instance will replace the original Instance after the method ends.

To use the mutating method, put the keyword mutating before the func keyword of the method:

Struct Point {varx = 0.0, y = 0.0 mutating func moveByX (deltaX: Double, y deltaY: Double) {x + = deltaX y + = deltaY} var somePoint = Point (x: 1.0, y: 1.0) somePoint. moveByX (2.0, y: 3.0) println ("The point is now at (\ (somePoint. x), \ (somePoint. y) ") // output" The point isnow at (3.0, 4.0 )"


The Point struct above defines a mutating method moveByX, which is used to move a vertex. The moveByX method modifies this vertex when called, instead of returning a new vertex. The mutating keyword is added to the method definition so that the method can modify the attribute of the value type.

Note: you cannot call the mutation method on a struct type constant because the attributes of a constant cannot be changed, even if you want to change the attributes of a constant. For more information, see storage attributes and instance variables.

let fixedPoint = Point(x: 3.0, y: 3.0)fixedPoint.moveByX(2.0, y: 3.0)// this will report an error


Assign a value to self in the mutation Method (Assigning to self Within a Mutating Method)

The mutation method can assign a brand new instance to the hidden property self. The above Point example can be rewritten in the following way:

struct Point {  varx = 0.0, y = 0.0 mutating func moveByX(deltaX: Double, y deltaY: Double) {   self = Point(x: x + deltaX, y: y + deltaY)  }}


The new variant method moveByX creates a new structure (both its x and y values are set as the target values ). The method for calling this version is the same as that for calling the previous version.

You can set self to different members of the same Enumeration type as the enumeration variation method:

Enum TriStateSwitch {case Off, Low, High mutating func next () {switch self {case Off: self = Low case Low: self = High case High: self = Off }}var ovenLight = TriStateSwitch. lowovenLight. next () // ovenLight is now equal. highovenLight. next () // ovenLight is now equal. off


The preceding example defines an enumeration of three-state switches. Each time you call the next method, the switch switches cyclically before the power status (Off, Low, High.

Type Method)

The instance method is called by a type instance. You can also define the method called by the type itself. This method is called the type method. Declare the type method of the class, add the keyword class before the func keyword of the method, declare the struct and enumeration type method, and add the keyword static before the func keyword of the method.

Note:

In Objective-C, you can only define type methods (type-level methods) for Objective-C classes ). In Swift, you can define type methods for all classes, struct, and enumeration: Each type method is explicitly included by the supported types.

The type method is called using the dot syntax like the instance method. However, you call this method at the type level, rather than at the instance level. The following is an example of how to call a type method on the SomeClass class:

class SomeClass { class func someTypeMethod() {   // type method implementation goes here  }}SomeClass.someTypeMethod()


In the method body of the type method, self points to the type itself, rather than a type instance. For struct and enumeration, this means that you can use self to eliminate ambiguity between static attributes and static method parameters (similar to what we did before processing instance attributes and instance method parameters ).

In general, any undefined method and attribute names will come from methods and attributes of another type level in this class. One type method can call the name of another type method in this class, without adding the type name prefix before the method name. Similarly, the struct and enumeration type methods can directly access static properties through the static property name without the type name prefix.

The following example defines a struct named LevelTracker. It monitors the game development of players (different levels or stages of the game ). This is a single player, but it can also store Game Information of multiple players on the same device.

At the beginning of the game, all game levels (except level 1) were locked. Each time a player completes a level, it unlocks all players on the device. The LevelTracker struct uses static attributes and methods to monitor which level of the game has been unlocked. It also monitors the current level of each player.

struct LevelTracker { static var highestUnlockedLevel = 1 static func unlockLevel(level: Int) {   if level > highestUnlockedLevel { highestUnlockedLevel = level }  } static func levelIsUnlocked(level: Int) -> Bool {   return level <= highestUnlockedLevel  }  varcurrentLevel = 1 mutating func advanceToLevel(level: Int) -> Bool {   if LevelTracker.levelIsUnlocked(level) {     currentLevel = level     return true    }else {     return false    }  }}


LevelTracker monitors the highest level of unlocked players. This value is stored in the static property highestUnlockedLevel.

LevelTracker also defines two types of methods to work with highestUnlockedLevel. The first type method is unlockLevel: once the new level is unlocked, it will update the value of highestUnlockedLevel. The second type method is levelIsUnlocked: if a given level has been unlocked, it returns true. (Note: although we didn't use a method similar to LevelTracker. highestUnlockedLevel, this type of method can still access the static attribute highestUnlockedLevel)

In addition to static attributes and type methods, LevelTracker also monitors the progress of each player. It uses the instance property currentLevel to monitor the current player level.

To facilitate the management of the currentLevel attribute, LevelTracker defines the instance method advanceToLevel. This method checks whether the requested new level has been unlocked before updating currentLevel. The advanceToLevel method returns a Boolean value to indicate whether currentLevel can be set.

Below, the Player class uses LevelTracker to monitor and update the progress of each Player:

class Player {  vartracker = LevelTracker()  letplayerName: String func completedLevel(level: Int) {   LevelTracker.unlockLevel(level + 1)   tracker.advanceToLevel(level + 1)  } init(name: String) {   playerName = name  }}


The Player class creates a new LevelTracker instance to monitor the user's development progress. He provides the completedLevel method: it is called once the player completes a specified level. This method unlocks the next level for all players and updates the progress of the current player to the next level. (We ignored the Boolean value returned by advanceToLevel because we knew this level had been unlocked when calling LevelTracker. unlockLevel ).

You can also create a Player instance for a new Player, and then see what happens when the Player completes the level:

Var player = Player (name: "Argyrios") player. completedLevel (1) println ("highest unlocked level is now \ (LevelTracker. highestUnlockedLevel) ") // output" highestunlocked level is now 2 "(the highest level is 2)


If you create a second player and try to start a level that is not unlocked by any player, this attempt to set the current level of the player will fail:

Player = Player (name: "Beto") if player. tracker. advanceToLevel (6) {println ("player is now on level6")} else {println ("level 6 has not yet beenunlocked ")} // output "level 6 hasnot yet been unlocked" (level 6 is not unlocked yet)


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.