协议可以用来定义方法、属性、下标的声明,协议可以被枚举、结构体、类遵守(多个协议之间用逗号隔开)
protocol Drawable {
func draw()
var x: Int { get set }
var y: Int { get }
subscript(index: Int) -> Int { get set }
}
protocol Test1 { }
protocol Test2 { }
protocol Test3 { }
class TestClass: Test1, Test2, Test3 { }
协议中定义方法时,不能有默认参数值
默认情况下,协议中定义的内容必须全部都实现
也有办法办到只实现部分内容,以后的会讲到
协议中定义属性时必须要用var关键字
实现协议时的属性权限要不小于协议中定义的属性权限
协议定义get、set,用var存储属性或者get、set计算属性去实现
协议定义get,用任意属性实现都可以 接上
class Person: Drawable {
var x: Int = 0
let y: Int = 0
func draw() {
print("Person draw")
}
class func drawSt() {
print("person类draw")
}
subscript(index: Int) -> Int {
set {}
get { index }
}
}
class Person2: Drawable {
var x: Int {
get { 0 }
set { }
}
var y: Int { 0 }
func draw() {
print("Person draw")
}
static func drawSt() {
print("person类draw")
}
subscript(index: Int) -> Int {
set {}
get { index }
}
}
static、class
为了保证通用,协议中必须用static定义类型方法、类型属性、类型下标
mutating
只有奖协议中的实例方法标记为mutating 才允许结构体、枚举的具体实现修改自身内存,类在实现方法时不用加mutating,枚举,结构体才需要加mutating
protocol Drawable {
mutating func draw()
}
class Person: Drawable {
var width: Int = 2
func draw() {
width = 34
print("Person draw")
}
}
struct Point: Drawable {
var x: Int = 1
mutating func draw() {
x = 344
}
}
init
协议中还可以定义初始化器init。非final类实现时必须加上required
protocol Drawable {
init(x: Int, y: Int)
}
class Person: Drawable {
required init(x: Int, y: Int) { }
}
final class Perosn22: Drawable {
init(x: Int, y: Int) { }
}
如果子类也需要实现的话就加上reruired,final就是没有子类了,所以不需要加上required
如果从协议实现的初始化器,刚好是重写了父类的指定初始化器 那么这个初始化器必须同时加上required、override
protocol Drawable {
init(x: Int, y: Int)
}
class Person {
init(x: Int, y: Int) { }
}
class Perosn22:Person, Drawable {
required override init(x: Int, y: Int) { }
}
init、init?、init!
协议中定义的init?、init!,可以用nit、init?、init!去实现
协议总定义的init,可以用nit、init!去实现
协议的继承
一个协议可以继承其他协议
protocol Drawable {
func test1()
}
protocol Drawable2: Drawable {
func test2()
}
class Person: Drawable, Drawable2{
func test1() {}
func test2() {}
}
协议组合,可以包含一个类类型(最多1个)不是结构体也不是枚举只能是类
CaseIterable
让枚举遵守CaseIterable协议,可以实现遍历枚举值
enum Seasons: CaseIterable {
case sping, summer, autumn, winter
}
let seasons = Seasons.allCases
print(seasons.count) // 4
for season in seasons {
print(season)
}
CustomStringConvertible
遵守CustomStringConvertible协议,可以自定义实例的打印字符串
class Person: CustomStringConvertible {
var age: Int
var name: String
init(age: Int, name: String) {
self.age = age
self.name = name
}
var description: String {
"age=\(age), name=\(name)"
}
}
var p = Person(age: 10, name: "dff")
print(p)
代理
代理,在协议的基础上,默认一般的都是必须实现的方法,可选的用@objc optional. NSObjectProtocol:可加可不加,如果需要里面的方法则加,如果不需要则不加
@objc protocol ViewDelegate : NSObjectProtocol {
func scrollTotalItemCount(_ scrollView: ScrollView) -> Int
@objc optional func scrollViewItemHeight(_ scrollView: ScrollView) -> Float
}
class ScrollView: UIView {
weak var delegate: ViewDelegate?
}
class ScrollViewComponet : NSObject {
init(frame:CGRect, superView: UIView) {
self.scrollView : ScrollView = ScrollView(frame: frame)
super.init()
scrollView.delegate = self
superView.addSubview(scrollView)
}
}
extension ScrollViewComponet : ViewDelegate {
func scrollTotalItemCount(_ scrollView: ScrollView) -> Int {
3
}
}
还有,可以直接给协议加extention。可以达到默认实现。
Any、AnyObject
Swift提供了2种特殊的类型:Any、AnyObject
Any:可以代表任意类型(枚举、结构体、类,也包括函数类型)
AnyObject:可以代表任意类类型(在协议后面写上:AnyObject代表只有类能遵守这个协议)
var stu: Any = 10
stu = "KAs"
stu = Student()
// 创建1个能存放任意类型的数组
//var data = Array<Any>()
var data = [Any]()
data.append(1)
data.append(2.32)
data.append(Student())
data.append("JAss")
data.append({39})
is、as?、as!、as
is是用来判断是否为某种累心个,as用来做强制类型转换
X.self、X.Type、AnyClass
X.self是一个元类型(metadata)的指针,metadata存放着类型相关信息
X.self属于X.Type类型
Self代表当前类型