A type conversion can determine the type of an instance, or it can be considered an instance of its parent class or child class.
Type conversions are implemented in Swift using is
and as
operators. These two operators provide a simple way to check the type of a value or convert its type.
You can also use it to check whether a class implements a protocol, as described in the conformance section of the validation protocol.
Define a class hierarchy as an example
You can use type conversions on hierarchies of classes and subclasses, examine the type of instances of a particular class, and convert the type of instances of that class into other types in that hierarchy. The following three code snippets define a class hierarchy and an array containing several instances of these classes as examples of type conversions.
The first code fragment defines a new base class MediaItem
. This class provides the underlying functionality for any media item that appears in the digital library. In particular, it declares a String
type of name
property, and an init name
initializer. (Assume that all media items have a name.) )
class MediaItem { var name: String init(name: String) { self.name = name }}
The next code snippet defines MediaItem
the two subclasses. The first subclass Movie
encapsulates additional information related to the movie, adding a (director) attribute to the parent class (or base Class) director
, and the corresponding initializer. The second subclass, on the Song
basis of the parent class, adds an artist
(artist) attribute, and the corresponding initializer:
class Movie: mediaitem {var Director: String init (name:string, director:string) {Self.director = Director Super.init (name:name)}}class song: Mediaitem {var Artist: string init (name:string, artist:string) {self.artist = artist Super.init (Name:name)}}
The last code snippet creates an array constant library
that contains two Movie
instances and three Song
instances. library
is inferred from the content contained in its array when it is initialized. Swift's type detectors can Movie
infer and have a Song
common parent class MediaItem
, so it infers the [MediaItem]
type as the class library
.
Let library = [Movie (Name"Casablanca",Director"Michael Curtiz"), Song (name: "Blue Suede Shoes", "Elvis Presley"), Movie (name: "Citizen Kane", director: Orson Welles "), Song (name: " The One and only ", artist: name: "Never Gonna Give You Up", artist: "Rick Astley ")]//the type of " library " Span class= "Hljs-keyword" >is inferred to be [Mediaitem]
The library
media items stored behind the scenes are still the same Movie
Song
type. However, if you iterate over it, the instance that is taken out in turn will be of MediaItem
type, not Movie
and Song
type. In order for them to work as the original type, you need to check their types or convert them down to other types, as described below.
Check type (Checking type)
Use the Type check operator ( is
) to check whether an instance belongs to a particular subtype. If the instance belongs to that subtype, the type check operator returns true
, otherwise returns false
.
The following example defines two variables, movieCount
and songCount
is used to calculate the library
number of instances in the array Movie
and Song
type.
var moviecount = 0var songcount = 0 For item in Library {if item is Movie {++moviecount} else if item is Song {++songcount}}print ( "Media library contains \ ( Moviecount) Movies and \ (songcount) songs ") //prints " Media Library contains 2 movies and 3 songs " /span>
The example iterates over library
all the items in the array. Each time, for
-the in
loop item
is set to the next in the array MediaItem
.
Returns if MediaItem
it is currently an Movie
instance of a type item is Movie
true
false
. Similarly, item is Song
Check if item is an Song
instance of type. At the end of the loop, movieCount
songCount
The value is the number of instances that are found to belong to their respective type.
Down Transformation (downcasting)
A constant or variable of a type may actually belong to a subclass behind the scenes. When you are sure that this is the case, you can try to go down to its sub-type, with the type conversion operator ( as?
or as!
)
Because the downward transition may fail, the type transformation operator takes two different forms. The conditional form (conditional form) as?
Returns an optional value (optional value) of the type you are trying to turn down. Coercion forms as!
the attempt to transform downward and force unpack (force-unwraps) results as a mixed action.
When you are unsure if the downward transition can succeed, use the type conversion condition form ( as?
). Type conversions in conditional form always return an optional value (optional value), and the optional value will be if it is not possible to go down nil
. This allows you to check whether the downward transition is successful.
Only use coercion () if you can be sure that the downward transformation will succeed as!
. When you try to move down to an incorrect type, coercion of type conversions triggers a run-time error.
The following example iterates over library
each one MediaItem
and prints out the appropriate description. To do this, you item
need to Movie
use the real as or Song
the type, not just as MediaItem
. Movie
Song
director
artist
This is necessary in order to be able to use or attribute in the description.
In this example, each of the arrays item
may be Movie
or Song
. Beforehand you do not know item
the actual type of each, so here use the conditional form of the type conversion ( as?
) to check every turn in the loop.
For itemIn library {IfLet movie = Item as? Movie {Print"Movie: ' \ (movie.name) ', dir. \ (Movie.director)}}ElseIfLet song = Item as? Song {print ( "Song: ' \ (Song.name) ', by \ (song.artist)")}}//movie: ' Casablanca ', dir. Michael Curtiz//song: ' Blue Suede Shoes ' , by Elvis presley//Movie: ' Citizen Kane ', dir. Orson welles//Song : ' The one and only ', by Chesney Hawkes //song: ' Never Gonna Give you Up ', by Rick Astley
The example first attempts to move item
down Movie
. Because it item
is an instance of a MediaItem
type, it may be one Movie
; again, it may be one Song
, or just a base class MediaItem
. Because it is indeterminate, the as?
form returns an optional value when attempting to move down. item as? Movie
The return value of the is Movie?
or "optional Movie
" type.
When you move down to an Movie
app in two Song
instances, it will fail. To deal with this situation, the above example uses an optional binding (optional binding) to check that an optional Movie
true contains a value (this is to determine if the transfer succeeds.) The optional bindings are written in this way if let movie = item as? Movie
, and can be interpreted like this:
"Attempt to convert to item
Movie
type. If successful, set a new temporary constant movie
to store the returned optional Movie
"
If the downward transformation succeeds, then movie
the property will be used to print the description of an Movie
instance, including its director's name director
. A similar principle is used to detect an Song
instance and Song
print its description (included name) when it is found artist
.
Attention:
The conversion does not really change the instance or its value. The underlying root instance remains the same, simply using it as the class it is converted to.
Any
And
AnyObject
The type conversion
Swift provides two special types of aliases for indeterminate types:
AnyObject
Can represent instances of any class type.
Any
can represent any type, including the method type (function types).
Attention:
Use and only when you explicitly need its behavior and functionality Any
AnyObject
. It's always better to use the explicit type you expect in your code.
AnyObject
Type
When using Cocoa APIs at work, we typically receive an array of one [AnyObject]
type, or "an array of any object type." This is because OBJECTIVE-C does not have an explicit typed array. However, you can often clearly determine the type of objects in an array from the information provided by the API.
In these cases, you can use the coerced form of the type conversion ( as
) to go down each item in the array to a AnyObject
more explicit type than the one that requires optional parsing (optional unwrapping).
The following example defines an [AnyObject]
array of type and fills in an Movie
instance of three types:
let someObjects: [AnyObject] = [ Movie(name: "2001: A Space Odyssey", director: "Stanley Kubrick"), Movie(name: "Moon", director: "Duncan Jones"), Movie(name: "Alien", director: "Ridley Scott")]
Because you know that the array contains only Movie
instances, you can as!
go down and unpack to the non-selectable type directly () Movie
:
for object in someObjects { let movie = object as! Movie print("Movie: ‘\(movie.name)‘, dir. \(movie.director)")}// Movie: ‘2001: A Space Odyssey‘, dir. Stanley Kubrick// Movie: ‘Moon‘, dir. Duncan Jones// Movie: ‘Alien‘, dir. Ridley Scott
In order to become a shorter form, the down-turn someObjects
array is a [Movie]
type that replaces the way each item in the array is converted.
for movie in someObjects as! [Movie] { print("Movie: ‘\(movie.name)‘, dir. \(movie.director)")}// Movie: ‘2001: A Space Odyssey‘, dir. Stanley Kubrick// Movie: ‘Moon‘, dir. Duncan Jones// Movie: ‘Alien‘, dir. Ridley Scott
Any
Type
Here's an example of using Any
types to work with different types of blending, including method types and non- class
types. It creates an Any
array of types that can be stored things
.
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"))things.append({ (name: String) -> String in "Hello, \(name)" })
things
The array contains two Int
values, 2 Double
values, 1 String
values, a tuple (Double, Double)
, the movie "Ghostbusters", and a closure expression that gets String
the value and returns another String
value.
You can switch
use and manipulate in the cases of an expression to is
as
find only the type Any
of AnyObject
constant or variable that you know is OR. The following example iterates through things
each item in the array and uses the switch
statement to find the type of each item. The switch
cases of these statements bind their matching values to a constant of the specified type, so that their values can be printed:
For thingIn Things {Switch thing {Case0As Int:print ("Zero as an Int")Case0As Double:print ("Zero as a Double")CaseLet SomeintAs Int:print ("An integer value of \ (Someint)")CaseLet SomedoubleAs Double where somedouble >0:print ("A positive double value of \ (somedouble)")Case is Double:print ("Some other double value that I don ' t want to print")CaseLet somestringAsString:print ("A string value of \" \ (somestring) \ "")CaseLet (x, y)As (double, double): print ("An (x, y) point at \ (x), \ (y)")CaseLet movieAs Movie:print ( "a movie called ' \ (movie.name) ', dir. \ (movie.director)") case let stringconverter as string, string:print (Stringconverter ( default:print ( "something Else")}} //Zero as an int//Zero as a double/ /An integer value of 42//a positive double value of 3.14159//a St Ring value of "Hello" //an (x, y) point at 3.0, 5.0//a movie called ' Ghostbusters ', dir. Ivan reitman//Hello, Michael
Details turn from: http://wiki.jikexueyuan.com/project/swift/chapter2/07_Closures.html
Attack on Swift-----------type conversion