http://blog.csdn.net/mengxiangyue/article/details/43437797
Original address: Http://www.raywenderlich.com/80818/operator-overloading-in-swift-tutorial Corinne krych Translator: Mengxiang Month blog:http:// Blog.csdn.net/mengxiangyue
This article is my first translation, inevitably there is a mistake, the translation of the use of TXT, so the format is not very good.
In an earlier tutorial on the iOS 8 feast series, you've learned that Swift offers many powerful, modern programming features, such as generics, functional programming, enumeration of first class, struct body, and so on.
But now there's another swift feature that you should know and fall in love with, which is operator overloading.
This is a great way for you to use the + 、-、 *,/and other operators to act on any type you like. If you have some creativity, you can even define your own operator.
For example: We are in swift Sprite Kit utility library (https://github.com/raywenderlich/SKTUtils/tree/swift) The code uses operator overloading to tell the addition of multiple cgpoints objects, such as the following code:
Let pt1 = Cgpoint (x:10, y:20)
Let pt2 = Cgpoint (x: -5, y:0)
Let PT3 = pt1 + pt2
Let Pt4 = pt3 * 100
Is it convenient? Then start the reload now and boost your swift development capabilities.
Note: This swift Tutorial is based on the assumption that you already have the basic swift development capabilities. If you are new to Swift, we recommend that you study our other Swift Tutorials (http://www.raywenderlich.com/tutorials#swift) first.
operators: Overview
Note: This section of the content is optional, if you want to review the operators and their precedence, you can still see this part of the content. If you are already familiar with these, you can create an empty playground directly, and proceed to the next section: Overloading (overloading).
First we create a new playground to help you understand the operator.
Add the following code in your playground:
var simplesum = 1 + 3
You can see the results we want:
4
Here are two operators we are familiar with:
1 First, you define a variable called simplesum, and use the assignment operator (=) to set its value.
2 then you use the plus operator (+) to calculate the and of two integers.
In this tutorial, you will overload the operators like this. But first, you need to understand the concept of precedence.
Priority Level
You may remember the rules about operator precedence that you learned in math classes at school. These rules make certain operators have a higher priority than other operators, and high-priority operators are evaluated first. For example, the multiplication will be calculated before the addition or subtraction.
Enter the following code in your playground to verify that these rules are also followed in Swift.
var sumwithmultiplication = 1 + 3-3 * 2
You can see the following results:
-2
When the arithmetic operators have the same priority, Swift calculates the operators from left to right. In this example, the operators are calculated in the following order:
1.3 * 2: Minus (Translator note: This minus can be omitted, mainly to correspond to the third step)
2.1 + 3: The leftmost operator is evaluated first, as the operator takes precedence.
3.4-6: This operation relies entirely on the result of the operation of the preceding high-priority operator.
Note: If you want to know the list of priorities in Swift, you can be here (https://developer.apple.com/library/prerelease/mac/documentation/Swift/Conceptual/ swift_programming_language/expressions.html#//apple_ref/doc/uid/tp40014097-ch32-xid_720) Find the list of completed operator precedence.
Plus is not just able to use on the numbers (Adding Isn ' t Just for Ints)
The integer operation will run as we wish, but can you use the + to other types?
The following code proves that you can! In your playground, add the following code to try it out:
var sumarray = [1, 2] + [1, 2]
In this case, Swift interprets the + as the APPEND directive. But what if you want to add the elements of each position? We all know this is called vector addition (vectors addition).
Of course, you can define a method to implement this function, in your playground add the following code to try again:
Func Add (left: [Int.], right: [int]), [int] {
var sum = [Int] ()
ASSERT (Left.count = = Right.count, "Vector of same length only")
For (key, V) in enumerate (left) {
Sum.append (Left[key] + Right[key])
}
return sum
}
This way, you define a global approach that implements the addition of the two arrays that calculate the input, first detecting whether the lengths of the two input arrays are consistent, and then adding the elements from each of the two arrays and storing them in a new array.
Now add the following code to verify that your new method is working correctly:
var arr1 = [1, 1]
var arr2 = [1, 1]
var arr3 = Add (arr1, ARR2)
You will see the following output in the console:
[2, 2]
It's great! But we have to call a method to do it, why can't we use the + operator instead?
operator Overloading
Operator overloading allows you to change the way that existing operators work on specific structures and classes (the translator notes: It may be a bit messy). Isn't that what you want--changing the way the + operator works on an int array.
Because operator overloading is a function of the global playground, create a new playground that prevents you from affecting the example you originally wrote. Then add the following code to your playground:
Func + (left: [Int.], right: [int]), [int] {//1
var sum = [Int] ()//2
ASSERT (Left.count = = Right.count, "Vector of same length only")//3
For (key, V) in enumerate (left) {
Sum.append (Left[key] + Right[key])//4
}
return sum
}
You have defined a global function called +, which adds two int arrays and returns an int array. Let's break down how it works:
1. Note that this method defines nothing special. It is a common method definition except that you use + as its function name.
2. You have created an empty int array.
3. This example can only work on two arrays that are the same case, so use assert here to ensure that it is so.
4. Then you enumerate the array on the left, and add the value of the right array in the same position.
Add the following code to your playground to test this method:
var sumArray1 = [1, 2, 3] + [1, 2, 3]
Finally-the result of your expected vector addition operator appears! You will see the following result:
[2, 4, 6]
Of course, operator overloading is not always pleasant. When a person looks at your code, they want the default behavior of the operator, and this time the operator overloads confuse them. This, however, does not prevent you from rewriting the + operator to allow it to perform the subtraction of numbers, which of course is obvious.
Image Http://cdn4.raywenderlich.com/wp-content/uploads/2014/09/OperatorRage.png
Remember the principle of operator overloading: the greater the capacity the greater the responsibility (with great power comes great responsibility).
Typically, when you overload an operator on a new object, you need to maintain its original semantics, rather than defining different (and confusing) behaviors.
In this case, the overloaded behavior retains the original semantics: vector addition is still an addition. But when you override the default add behavior for an int array, you may want to use the int array for a few months to add the default behavior, which will be confusing to use.
Fortunately, Swift allows you to define your own custom operators.
Defining custom Operators
Here are three steps to define a custom operator:
1. Name your operator
2. Select a type
3. Set its priority and binding
Define your operator
Now you have to select a character as your operator. The custom operator can be/, = 、-、 +,! , *,%, <, >, &, |, ^, ~ or Unicode characters start. This gives you a lot of scope to choose your operator. But don't be too happy, when you choose, you must also consider the number of keystrokes you have to repeat when typing.
In this case, you can copy and paste the Unicode character ⊙ as well to adapt your example to the implementation of the addition.
Select a type
In Swift you can define the unary, two, and ternary operators. They indicate the number of operators that the operator operates.
A unary operator is associated with an operand, such as a post + + (i++) or a predecessor + + (++i), and they depend on where the operator and the operand appear.
The binary operator is inserted because it appears in the middle of two operators, such as 1 + 1.
The ternary operator has three operands. In Swift, the?: The conditional operator is the only three-mesh operator, such as A?B:C.
You should choose the appropriate type based on the number of operands of your operator. If you want to add two arrays together, define the two-tuple operator.
set its priority and binding
Because operator definitions are global, you should be careful to choose the precedence and binding of your custom operators.
This is very tricky, so there is a better way in Swift language Reference (https://developer.apple.com/library/mac/documentation/Swift/ Conceptual/swift_programming_language/expressions.html#//apple_ref/doc/uid/tp40014097-ch32-xid_ 720) find a similar standard operator, and then use the same semantics. For example, when you define a vector plus, you can use the same precedence and binding as the + operator.
Write your own custom operator
Go back to your playground and enter the following code to define your custom operator. For simplicity, you may want to copy and paste the ⊙. (Translator Note: This may refer to copying this character in the process of use)
Infix operator⊕{associativity left precedence 140}//1
Func⊕ (left: [Int.], right: [int]), [int] {//2
var sum = [Int] (Count:left.count, repeatedvalue:0)
ASSERT (Left.count = = Right.count, "Vector of same length only")
For (key, V) in enumerate (left) {
Sum[key] = Left[key] + Right[key]
}
return sum
}
This code is similar to the one you previously had in the first section, and this code does the following steps:
* Defines an infix/two-dollar operator that has two operands and is located on both sides of the operator.
* The name operator is ⊙.
* Set Associativity to left, indicating that the operator will use the order of the operators in the same priority when the sequence of the operator is used in the combination of the right.
* Set Priority to 140, this is the same priority as int addition, these priorities can be in swift language reference (https://developer.apple.com/library/mac/ Documentation/swift/conceptual/swift_programming_language/expressions.html#//apple_ref/doc/uid/ tp40014097-ch32-xid_720) view.
The second part of the code is similar to what you saw earlier, and it adds one of the two arrays in order. Add the following code to your playground to test the new operator:
var sumarray = [1, 2, 3]⊕[1, 2, 3]
You'll see the same results as the previous overloaded methods, but this time you have an operator with different semantics.
Bonus round!
Now that you know how to create a custom operator, it's time to challenge yourself. You have created a ⊙ operator to perform the addition of the vectors, so use the current knowledge to create an operator that uses a similar method to subtract two arrays. Try your best and then check out the answers below.
Infix operator? {associativity left precedence 140}
Func? (left: [Int.], right: [int]), [int] {
var minus = [Int] (Count:left.count, repeatedvalue:0)
ASSERT (Left.count = = Right.count, "Vector of same length only")
For (key, V) in enumerate (left) {
Minus[key] = Left[key]-Right[key]
}
return minus
}
Test:
var subtractionarray = [1, 2, 3]? [1, 2, 3]
Remember similar operators
If you define a new operator, don't forget to define any associated operators.
For example, the plus operator (+ =) combines a plus and an assignment of two operators into an operator. Since your new arithmetic semantics is the same as add, a good way is to also define an add equals operator.
Add the following code to Operator2.playground:
Infix operator⊕= {associativity left precedence 140}//1
Func⊕= (inout left: [Int.], right: [int]) {//2
left = Left⊕right
}
The first line is declared just like the ⊙ operator, which uses a combination operator.
Note the second line, which declares that the left input parameter of this combination operator is inout, which indicates that the value of this parameter will be modified directly inside the operator method. As a result, this operator does not return a value, it modifies your input value directly.
Add the following code to your playground to test whether the operator runs the way you want.
You will see the following output on the console:
[3, 5, 7]
Now look, it's not hard to define your own operators.
for more than just a type definition operator
Now imagine you also want to define a vector plus operator for decimals.
One way is for you to overload a new operator for double and float in the same way that you overload the operator for Int. It's just a few lines of code, but you have to use copy/paste. If you're like me--there's code cleanliness--Copying the code is not your first choice, it makes your code difficult to maintain.
Use generics to save
Fortunately, Swift generics can help you implement this feature. If you need to review Swift's generics, you can find our previously published article Swift generics Tutorial (http://www.raywenderlich.com/82572/swift-generics-tutorial).
In order to have a clean context, we create a new playground. Add the following code to your playground:
Infix operator⊕{associativity left precedence 140}
Func⊕<t> (left: [t], right: [t]), [t] {//1
var minus = [T] ()
ASSERT (Left.count = = Right.count, "Vector of same length only")
For (key, V) in enumerate (left) {
Minus.append (Left[key] + Right[key])//2
}
return minus
}
In the first line, you define a generic type of function ⊙, which has a type placeholder T. Playground is not happy to be here. You can see a compilation error: Could not find a overload for ' + ' that accepts the supplied arguments.
This error comes from the second line, and when we try to use the + operator on the two-type T-left and right two arguments, an error occurs. Swift does not know how it should use the + operator on these parameters, because it does not know what types these parameters are.
Extend a protocol
Remove your code and replace it with the following code:
Protocol number {//1
Func + (l:self, r:self), Self//2
}
Extension Double:number {}//3
Extension Float:number {}
Extension Int:number {}
Infix operator⊕{associativity left precedence 140}
Func⊕<t:number> (left: [t], right: [t]), [t] {//4
var minus = [T] ()
ASSERT (Left.count = = Right.count, "Vector of same length only")
For (key, V) in enumerate (left) {
Minus.append (Left[key] + Right[key])
}
return minus
}
You do a lot of things here, and we go back and break down these steps:
1. You have defined a protocol number
2. This number defines an operator +
3. You created an extension for double, float, and int to enable them to implement the number protocol
4. You use a type constraint to require T to implement the number protocol
Finally, you tell the compiler how t should handle the + operator. Now that you have fixed the compilation error, use the following code to test it with a double array and an array of int, respectively:
var doublearray = [2.4, 3.6]⊕[1.6, 2.4]
var intarray = [2, 4]⊕[1, 2]
You will see the following output on the console:
[4.0, 6.0]
[3, 6]
This operator now works correctly under a variety of data types and does not copy code. If you want to add more numeric types, you just need a simple life to implement the number protocol.
How else can I use operator overloading in real life?
Haven't you ever thought that if it doesn't work, I'll let you waste so much time on this tutorial? This section will show you a real example of how you can better use operator overloading in your project.
Operators and Cgpoints
For this demo, you will use the Sktutils library (Https://github.com/raywenderlich/SKTUtils/tree/swift), which is a handy collection of Sprite Kit helper classes, It was written for the second edition of the book, IOS Games by Tutorials (http://www.raywenderlich.com/store/ios-games-by-tutorials).
You can find the warehouse for this framework on GitHub. Enter the following code in your command line interface to clone a branch of this repository:
git clone https://github.com/raywenderlich/SKTUtils.git--branch Swift
What you download on GitHub is the zip of the zipped package for that repository branch.
Note: Starting with Xcode6 Beta 5, it became possible to introduce your own library in playground. All you need to do is bind the framework and playground in a workspace. If you want to know more about these, please read this article playground has never been so fun (http://corinnekrych.blogspot.fr/2014/08/ playground-has-never-been-so-fun.html).
Open the Skutils/examples/playground/skutils.xcodeworkspace and compile the project.
Then open the Myplayground.playground from within the Project navigator. Delete the contents of the present and add the following code:
Import Sktutils
Let pt1 = Cgpoint (x:10, y:20)
Let pt2 = Cgpoint (x: -5, y:0)
Let PT3 = pt1 + pt2
Let Pt4 = pt3 * 100
You may be surprised that you have successfully used the +, * operator on Cgpoint, and the compiler does not have an error.
{x ten y 20}
{x-5 y 0}
{x 5 y 20}
{x y 2,000}
This magic comes from the sktutils you introduce in the head. Let's take a closer look.
overloads in the Sktutils
Open the Sktutils/cgpoint+extension.swift file in the Project navigator. You will see an extension defined for Cgpoint that overloads the + and + = operators.
public Func + (Left:cgpoint, right:cgpoint), Cgpoint {
Return Cgpoint (X:left.x + right.x, Y:left.y + right.y)
}
public Func + = (inout left:cgpoint, Right:cgpoint) {
left = left + right
}
This code is similar to what you wrote earlier, just set the access control to public. The access control is constrained to be able to access your code in other source files and modules. Since Sktutils is a framework, it needs to be able to be accessed outside of its own module, so it is defined for public.
This trick explains clearly that it doesn't have a bit of magic, it's just a smart code.
Of course, in the game cgpoint addition and multiplication is also a very common operation, so in that book, the overloaded cgpoint operator simplifies the code, making it concise, easy to read. I believe you can find similar examples in your project.
Operator overloading is a powerful feature of Swift, and if you use it carefully, it will make your development more efficient.
What's the next thing to do?
You have come to the end of this tutorial and I hope you enjoy it! You can find the final playground here (http://cdn5.raywenderlich.com/wp-content/uploads/2014/09/OperatorsPlaygrounds.zip).
If you want to learn more about operator overloading and swift, you can check out our new book Swift by Tutorials (http://www.raywenderlich.com/store/swift-tutorials-bundle).
I hope you find a way to use operator overloading in your project! But remember: With great power comes great responsibility (the greater the capacity the greater the responsibility) –don ' t be Troll dev!;]
If you have any questions about this tutorial or operator overloading, you can join our discussion forum below.
Swift Tutorial operator overloading