协议和扩展
- 协议
//声明一个协议
protocol ExampleProtocol {
var simpleDesecription: String {get}
mutating func adjust()
}
//类、枚举和结构体都可以使用协议
class simpleClass: ExampleProtocol {
var simpleDescription: String = "A very simple class."
var anotherProperty: Int = 69105
func adjust() {
simpleDescription += " Now 100% adjusted."
}
}
var a = simpleClass()
a.adjust()
let aDescription = a.simpleDescription
struct SimpleStructure:ExampleProtocol {
var simpleDescription: String = "A simple structure"
mutating func adjust() {
simpleDescription += " (adjusted)"
}
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription
//但是,上面的代码在运行的时候会出现报错“error: type 'simpleClass' does not conform to protocol 'ExampleProtocol'
class simpleClass: ExampleProtocol {
”,//这是因为没有实现其中的set方法,就比如用tableviewdatasource的时候必须要实现两个方法。
//注意在声明协议的时候,mutating关键词的使用,因为swift中的协议不仅可以被class实现,也适用于struct和enum,所以我们在写给别人用的借口的时候需要考虑是否使用mutating来修饰方法,用mutating可以修改struct或enum的变量,另外,在使用class来实现带有mutating的方法的接口时,具体实现的前面是不需要加mutating修饰的,因为class可以随意更改自己的成员变量,在接口里用mutating修饰方法,对于class的实现是完全透明的,可以当做不村子。
protocol Vehicle
{
var numberOfWheels: Int {get}
var color: UIColor {get set}
mutating func changeColor()
}
struct MyCar: Vehicle {
let numberOfWheels = 4
var color = UIColor.blueColor()!
mutating func changeColor() {
color = UIColor.redColor()
}
}
- 扩展
使用扩展(extension)来为已有的类型添加功能,比如新的方法和计算属性。
if语句和强制去包装(forced unwrapping)
如果确定可选有值,可以追加!来访问该值,叹号的作用是“我知道这个可选有值,放心用吧,”,我们把这个操作叫做可选所对应的值的强制去包装(forced unwrapping)
检查类型
- is,as
用类型检查操作符(is)来检查一个实例是否属于特定子类型,若实例属于那个子类型,类型检查操作符返回true,否则返回false。
var movieCount = 0
var songCount = 0
for item in library {
if item is Movie {
++movieCount
} else if item is Song {
++songCount
}
}
println("Media library contains \(movieCount) movies and \(songCount) songs”)
//向下转型(Downcasting):定义一个变量,把它转换为其他类型。向下转型可能会失败,类型检查操作符带有两种不同形式,可选as?或者强制转型as!
for item in library {
if let movie = item as? Movie {
println("Movie: '\(movie.name)', dir. \(movie.director)")
} else if let song = item as? Song {
println("Song: '\(song.name)', by \(song.artist)")
}
}
- Any和AnyObject的类型检查
swift为不确定类型提供了两种特殊类型别名:
(1) AnyObject可以代表任何class类型的实例
(2) Any可以表示任何类型,除了方法类型(function types)
只有当你明确的需要它的行为和功能时才使用Any和AnyObject
AnyObject:当需要在工作中使用Cocoa APIs,它一般接受一个anyobject【】类型的数组,或者说“一个任何对象类型的数组”,这是因为OC没有明确的类型化数组,但是,你常常可以确定包含在仅从你知道的API信息提供的这样一个数组中的对象的类型。
在这些情况下,你可以使用强制形式的类型检查(as)来下转在数组中的每一项到比anyobject更明确的类型,不需要可选解析(optional unwrapping)
let someObjects: [AnyObject] = [
Movie(name: "2001: A Space Odyssey", director: "Stanley Kubrick"),
Movie(name: "Moon", director: "Duncan Jones"),
Movie(name: "Alien", director: "Ridley Scott")
]
for object in someObjects {
let movie = object as! Movie
print("Movie: '\(movie.name)', dir. \(movie.director)")
}
//如上所示,因为明确知道someObject数组里面都是Movie类型,所以用了as!下转并解析到不可选的Movie类型。
//为了变为一个更短的形式,下转someObjects数组为Movie[]类型来代替下转每一项方式。
for movie in someObjects as Movie[] {
println("Movie: '\(movie.name)', dir. \(movie.director)")
}
// Movie: '2001: A Space Odyssey', dir. Stanley Kubrick
// Movie: 'Moon', dir. Duncan Jones
// Movie: 'Alien', dir. Ridley Scott