Swift语言学习笔记(4)
2016-07-13 14:00
411 查看
类型转换(Type Casting)
类型转换在 Swift 中被实现为 is 和 as 运算符。其中 is 运算符用于类型检查(判断某个值的类型)。
而 as 运算符用于类型转换(将某个值转换成别的类型)。
class MediaItem { var name: String init(name: String) { self.name = name } } 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) } } let library = [ Movie(name: "Casablanca", director: "Michael Curtiz"), Song(name: "Blue Suede Shoes", artist: "Elvis Presley"), Movie(name: "Citizen Kane", director: "Orson Welles"), Song(name: "The One And Only", artist: "Chesney Hawkes"), Song(name: "Never Gonna Give You Up", artist: "Rick Astley") ] // the type of "library" is inferred to be [MediaItem] var movieCount = 0 var songCount = 0 for item in library { if item is Movie { movieCount += 1 } else if item is Song { songCount += 1 } } print("Media library contains \(movieCount) movies and \(songCount) songs") // Prints "Media library contains 2 movies and 3 songs" for item in library { if let movie = item as? Movie { print("Movie: \(movie.name), dir. \(movie.director)") } else if let 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
为了处理不确定的类型,Swift 提供了两种特殊的类型:
AnyObject 可以表示任何类类型的实例。
Any 可以表示任何类型(包括函数类型)的实例。
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)" }) for thing in things { switch thing { case 0 as Int: print("zero as an Int") case 0 as Double: print("zero as a Double") case let someInt as Int: print("an integer value of \(someInt)") case let someDouble as 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") case let someString as String: print("a string value of \"\(someString)\"") case let (x, y) as (Double, Double): print("an (x, y) point at \(x), \(y)") case let movie as Movie: print("a movie called \(movie.name), dir. \(movie.director)") case let stringConverter as (String) -> String: print(stringConverter("Michael")) 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 string value of "hello" // an (x, y) point at 3.0, 5.0 // a movie called Ghostbusters, dir. Ivan Reitman // Hello, Michael
访问控制(Access Control)
Swift提供了5种访问级别(Access Levels):open(模块间可访问可扩展级别,最高)
public(模块间可访问但不可扩展级别,较高)
internal(模块内访问级别,中等,缺省)
file-private(文件内访问级别,较低)
private(外围声明访问级别,最低)
注:这里模块是指作为独立单元来构建并发布,可以使用import关键字导入到其他模块的框架(Framework)或者应用程序(Application)。
// 类的访问级别 public class SomePublicClass {} internal class SomeInternalClass {} fileprivate class SomeFilePrivateClass {} private class SomePrivateClass {} // 常量,变量,函数的访问级别 public var somePublicVariable = 0 internal let someInternalConstant = 0 fileprivate func someFilePrivateFunction() {} private func somePrivateFunction() {} // 缺省的访问级别 class SomeInternalClass {} // implicitly internal let someInternalConstant = 0 // implicitly internal
单一模块的应用通常只需要使用缺省的 internal 访问级别。
框架的 API 应该使用 open 以及 public 访问级别。
单元测试模块可以访问应用程序模块中所有 internal 访问级别的实体。
(需要@testable特性声明该实体并且使用testing enabled编译设置来编译product模块)
访问控制原则:任何实体都不能用低于自己的访问级别的其他实体来定义。
类型的访问级别会影响其成员(属性,方法,构造器,下标)和嵌套类型的访问级别。
file-private 以及 private 类型的成员和嵌套类型的缺省访问级别分别为 file-private 和 private。
public 或者 internal 类型的成员和嵌套类型的缺省访问级别为 internal。
// 缺省访问级别 public class SomePublicClass { // explicitly public class public var somePublicProperty = 0 // explicitly public class member var someInternalProperty = 0 // implicitly internal class member fileprivate func someFilePrivateMethod() {} // explicitly file-private class member private func somePrivateMethod() {} // explicitly private class member } class SomeInternalClass { // implicitly internal class var someInternalProperty = 0 // implicitly internal class member fileprivate func someFilePrivateMethod() {} // explicitly file-private class member private func somePrivateMethod() {} // explicitly private class member } fileprivate class SomeFilePrivateClass { // explicitly file-private class func someFilePrivateMethod() {} // implicitly file-private class member private func somePrivateMethod() {} // explicitly private class member } private class SomePrivateClass { // explicitly private class func somePrivateMethod() {} // implicitly private class member }
元组的访问级别会被自动推导为元组成员中最低的访问级别。
函数的访问级别不得高于该函数的参数类型和返回类型的访问级别。
private func someFunction() -> (SomeInternalClass, SomePrivateClass) { // ... }
枚举中成员的访问级别继承自该枚举,不能单独指定。
枚举的原始值和关联值的访问级别不能低于枚举的访问级别。
子类的访问级别不得高于父类的访问级别。
但是子类成员的访问级别可以高于它所覆盖的父类成员的访问级别。
只要符合访问控制原则,子类成员甚至可以调用具有较高访问级别的父类成员。
public class A { private func someMethod() {} } internal class B: A { override internal func someMethod() {} }
public class A { private func someMethod() {} } internal class B: A { override internal func someMethod() { super.someMethod() } }
常量,变量,属性不能拥有比自身类型更高的访问级别。
下标的访问级别不得高于该下标的索引类型和返回类型的访问级别。
常量,变量,属性,下标的Getters和Setters的访问级别继承自它们所属的常量,变量,属性,下标的访问级别。
struct TrackedString { private(set) var numberOfEdits = 0 var value: String = "" { didSet { numberOfEdits += 1 } } } var stringToEdit = TrackedString() stringToEdit.value = "This string will be tracked." stringToEdit.value += " This edit will increment numberOfEdits." stringToEdit.value += " So will this one." print("The number of edits is \(stringToEdit.numberOfEdits)") // Prints "The number of edits is 3" public struct TrackedString { public private(set) var numberOfEdits = 0 public var value: String = "" { didSet { numberOfEdits += 1 } } public init() {} }
自定义构造器的访问级别可以低于或等于它所属类型的访问级别。
但是必要构造器的访问级别必须和所属类型的访问级别相同。
private类型的缺省构造器的访问级别为private。
public或者internal类型的缺省构造器的访问级别为internal。
如果结构体中的任一存储属性的访问级别为private,那么它缺省的成员逐一构造器访问级别就是private。
否则该成员逐一构造器的访问级别为internal。
协议中的所有需求(方法及属性)都具有和该协议相同的访问级别,不能单独指定。
与其它类型不同的是,public访问级别的协议中的所有需求也将是public访问级别。
继承了别的协议的协议所拥有的访问级别最高也只能与被继承协议的访问级别相同。
采纳了协议的类型的访问级别取决于类型本身的访问级别以及该类型所采纳的任何协议的访问级别中最低的一方。
扩展成员缺省具有和原始类型成员相同的访问级别。
采纳了协议的扩展的成员的访问级别与所采纳协议的访问级别相同,不能单独指定。
泛型类型或泛型函数的访问级别取决于以下访问级别中最低的一方。
该泛型类型或泛型函数本身的访问级别
任何施加于该泛型类型或泛型函数的类型参数之上的类型约束的访问级别
一个类型别名的访问级别不可高于它所指向类型的访问级别。
高级运算符(Advanced Operators)
位运算符// 按位取反运算符(~) let initialBits: UInt8 = 0b00001111 let invertedBits = ~initialBits // equals 11110000 // 按位与运算符(&) let firstSixBits: UInt8 = 0b11111100 let lastSixBits: UInt8 = 0b00111111 let middleFourBits = firstSixBits & lastSixBits // equals 00111100 // 按位或运算符(|) let someBits: UInt8 = 0b10110010 let moreBits: UInt8 = 0b01011110 let combinedbits = someBits | moreBits // equals 11111110 // 按位异或运算符(^) let firstBits: UInt8 = 0b00010100 let otherBits: UInt8 = 0b00000101 let outputBits = firstBits ^ otherBits // equals 00010001 // 按位左移运算符(<<)和按位右移运算符(>>) let shiftBits: UInt8 = 4 // 00000100 in binary shiftBits << 1 // 00001000 shiftBits << 2 // 00010000 shiftBits << 5 // 10000000 shiftBits << 6 // 00000000 shiftBits >> 2 // 00000001 let pink: UInt32 = 0xCC6699 let redComponent = (pink & 0xFF0000) >> 16 // redComponent is 0xCC, or 204 let greenComponent = (pink & 0x00FF00) >> 8 // greenComponent is 0x66, or 102 let blueComponent = pink & 0x0000FF // blueComponent is 0x99, or 153
溢出运算符:
溢出加法 &+
溢出减法 &-
溢出乘法 &*
var potentialOverflow = Int16.max // potentialOverflow equals 32767, which is the maximum value an Int16 can hold potentialOverflow += 1 // this causes an error var unsignedOverflow = UInt8.max // unsignedOverflow equals 255, which is the maximum value a UInt8 can hold unsignedOverflow = unsignedOverflow &+ 1 // unsignedOverflow is now equal to 0 var unsignedOverflow = UInt8.min // unsignedOverflow equals 0, which is the minimum value a UInt8 can hold unsignedOverflow = unsignedOverflow &- 1 // unsignedOverflow is now equal to 255 var signedOverflow = Int8.min // signedOverflow equals -128, which is the minimum value an Int8 can hold signedOverflow = signedOverflow &- 1 // signedOverflow is now equal to 127
运算符的优先级和结合性
运算符函数
struct Vector2D { var x = 0.0, y = 0.0 } func + (left: Vector2D, right: Vector2D) -> Vector2D { return Vector2D(x: left.x + right.x, y: left.y + right.y) } let vector = Vector2D(x: 3.0, y: 1.0) let anotherVector = Vector2D(x: 2.0, y: 4.0) let combinedVector = vector + anotherVector // combinedVector is a Vector2D instance with values of (5.0, 5.0) // 前缀和后缀运算符 prefix func - (vector: Vector2D) -> Vector2D { return Vector2D(x: -vector.x, y: -vector.y) } let positive = Vector2D(x: 3.0, y: 4.0) let negative = -positive // negative is a Vector2D instance with values of (-3.0, -4.0) let alsoPositive = -negative // alsoPositive is a Vector2D instance with values of (3.0, 4.0) // 复合赋值运算符 func += (inout left: Vector2D, right: Vector2D) { left = left + right } var original = Vector2D(x: 1.0, y: 2.0) let vectorToAdd = Vector2D(x: 3.0, y: 4.0) original += vectorToAdd // original now has values of (4.0, 6.0) // 等价运算符 func == (left: Vector2D, right: Vector2D) -> Bool { return (left.x == right.x) && (left.y == right.y) } func != (left: Vector2D, right: Vector2D) -> Bool { return !(left == right) } let twoThree = Vector2D(x: 2.0, y: 3.0) let anotherTwoThree = Vector2D(x: 2.0, y: 3.0) if twoThree == anotherTwoThree { print("These two vectors are equivalent.") } // Prints "These two vectors are equivalent." // 自定义运算符 prefix func +++ (inout vector: Vector2D) -> Vector2D { vector += vector return vector } var toBeDoubled = Vector2D(x: 1.0, y: 4.0) let afterDoubling = +++toBeDoubled // toBeDoubled now has values of (2.0, 8.0) // afterDoubling also has values of (2.0, 8.0) // 自定义中缀运算符的优先级和结合性 infix operator +- { associativity left precedence 140 } func +- (left: Vector2D, right: Vector2D) -> Vector2D { return Vector2D(x: left.x + right.x, y: left.y - right.y) } let firstVector = Vector2D(x: 1.0, y: 2.0) let secondVector = Vector2D(x: 3.0, y: 4.0) let plusMinusVector = firstVector +- secondVector // plusMinusVector is a Vector2D instance with values of (4.0, -2.0)
相关文章推荐
- swift学习笔记之--方法
- 自学swift (2) ---修饰符(后续补充中)
- swift中获取命名空间
- Swift - 属性观察者(willSet与didSet)
- swift去除掉指定分割线
- 自学swift (1)
- 对照Java学习Swift--集合类型
- What's new in Swift 3
- Swift中的"可溢出"算术运算符
- Swift中的"可溢出"算术运算符
- Swift中的"可溢出"算术运算符
- swift - 内存管理
- swift (一) option理解
- swift利用Alamofire上传图片
- 太阳升起并下落的小动画-SWIFT
- Swift中新建的文件报错:no such module 'cocoa'
- swift学习笔记之—自定义函数的规则说明
- Swift利用闭包(closure)来实现传值-->前后两个控制器的反向传值
- 成长小计-Swift下的DEBUG打印数据
- 成长小计-Swift重写frame的set方法