Deep analysis of support for case data type matching by switch statements in Swift _swift

Source: Internet
Author: User
Tags case statement


Swift can match the values of different data types in the switch:


var things = Any[]()

things.append(0)
things.append(0.0)
things.append(42)
things.append(3.14159)
things.append("hello")
things.append((3.0, 5.0))
things.append(Movie(name:"Ghostbusters", director:"Ivan Reitman"))

for thing in things {
 switch thing {
 case 0 as Int:
 println("zero as an Int")
 case 0 as Double:
 println("zero as a Double")
 case let someInt as Int:
 println("an integer value of (someInt)")
 case let someDouble as Double where someDouble > 0:
 println("a positive double value of (someDouble)")
 case is Double:
 println("some other double value that I don't want to print")
 case let someString as String:
 println("a string value of "(someString)"")
 case let (x, y) as (Double, Double):
 println("an (x, y) point at (x), (y)")
 case let movie as Movie:
 println("a movie called '(movie.name)', dir. (movie.director)")
default:
 println("something else")
}
}

// zero as an Int
// zero as a Double
// an integer value of 42
// a positive double value of 3.14159
// a string value of"hello"
// an (x, y) point at 3.0, 5.0
// a movie called 'Ghostbusters', dir. Ivan Reitman


This will be matched according to the value of thing, to the corresponding case.



A question suddenly came to my mind today, which made me feel the need to summarize the switch statement. We know that the switch in Swift is far more powerful than the C language, but the question is, what types can be compared in the switch?



The official document explains the use of switch:



Cases can match many different patterns, including interval, matches tuples, and casts to a specific type.
That is, in addition to the most commonly used comparison integers, strings, and so on, the switch can also be used to match ranges, tuples, conversions to a particular type, and so on. But this including in the document is really silent because it does not indicate all the types that can be compared in the switch, and the questions raised at the beginning of the article still have no answer.



We might as well try to match the object with the switch:


Class A {

}

var o = a ()
var O1 = a ()
var O2 = A ()

switch o {case
O1:
  print (' It is O1 ')
CA Se O2:
  print (' It is O2 ')
default:
  print ("Not O1 or O2")
}


Sure enough, the compiler gave an error: "Expression pattern of type ' a ' cannot match values of type ' a '". At least we still do not understand what "expression pattern" is, how type a can not match type a.



Let's make a change, and we'll put it behind the case statement:


Switch o {case let
O1:
  print (' It is O1 ') case let
O2:
  print (' It is O2 ')
default:
  print ("Not O1 or O2 ")
}


OK, compile run, result: it is O1. This is because case let is not a matching value, but a value binding, that is, assigning the value of O to the temporary variable O1, which is useful when O is an optional type, similar to an implicit parsing optional type like if let. The It is O2 was not played because the switch in Swift matched only the first matching case, and then ended, and did not jump to the back if the break was not written.



Pull away, back to the topic, since add let not, we have to think of other ways. Consider how the switch statement is implemented at this time. According to my own guess, it is similar to using a lot of if to determine whether there is a matching case, then we give type A to overload the = = Operator Try:


Class A {}

func = = (Lhs:a, rhs:a)-> Bool {return true}

var o = a (); var O1 = a (); var O2 = A ()

Swit Ch o {case
O1:
  print (' It is O1 ') case
O2:
  print (' It is O2 ')
default:
  print ("Not O1 or O2")
}


Apparently, it failed again. If this can fix the problem, then this article is too water. The error message is the same as before. The problem is that we have overloaded the = = operator, why a type is still not hungry to match a type, do not switch does not determine whether two variables are equal.



Switch as a multiple conditional matching statement, it is natural to determine whether the variable is equal, but it is not through the = = operator to judge, but through the ~= operator. Take another look at an explanation of the official document:



An expression pattern represents the value of a expression. Expression patterns appear only in the switch statement case labels.
And this sentence:



The expression represented by the expression pattern are compared with the value of an input expression using the Swift STA Ndard Library ~= operator.
The first sentence explains the previous error, and the so-called "express pattern" refers to the value of the expression, which is only available in the Case tab of the switch. So the previous error message is: "O1 the value of this expression (or O1) and the incoming argument o are type a, but they cannot match." As for why not, the answer is in the second sentence, because the O1 and O matches are done by calling the ~= operator in the standard library.



So, as long as the overload = to replace the overload ~= on it. Change one character, nothing else, and then the program can run. Swift defaults to calling the = = operator in the ~= operator, which is why we do not feel the extra processing required to match the integer type. For custom types, however, ~= operators are not overloaded, even if you overload the = = is useless.



In addition, there is a workaround, that is, let a type implement equatable protocol. This does not require overloading the ~= operator. The answer lies in the last few lines of Swift's module:


@warn_unused_result Public
func ~=<t:equatable> (a:t, b:t)-> Bool


Swift has overloaded the ~= operator for all classes that implement the Equatable protocol. Although implementing the Equatable protocol only requires overloading the = = operator, Swift is not aware of the Equatable agreement if you do not explicitly specify it. Therefore, if you overload the = = operator, you can easily mark the implementation of the Equatable agreement, so there are many benefits, such as the Sequencetype split method.



Finally, a summary of the sentence:



Types that can be placed in a switch statement must overload the ~= operator, or implement the Equatable protocol.


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.