目录
comparable协议的使用
/// 一、comparable协议的使用
struct Student : Comparable {
/**
score大的比较大,若score相等,age小的比较大
要想比较2个实例的大小,一般做法是:
遵守 Comparable 协议
重载相应的运算符
*/
var age: Int
var score: Int
init(score: Int, age: Int) {
self.score = score
self.age = age
}
static func < (lhs: Student, rhs: Student) -> Bool {
(lhs.score < rhs.score) || (lhs.score == rhs.score && lhs.age > rhs.age)
}
static func > (lhs: Student, rhs: Student) -> Bool {
(lhs.score > rhs.score) || (lhs.score == rhs.score && lhs.age < rhs.age)
}
static func <= (lhs: Student, rhs: Student) -> Bool {
!(lhs > rhs)
}
static func >= (lhs: Student, rhs: Student) -> Bool {
!(lhs < rhs)
}
}
func compareableUse(){
let stu1 = Student(score: 100, age: 20)
let stu2 = Student(score: 98, age: 18)
let stu3 = Student(score: 100, age: 20)
print(stu1 > stu2) // true
print(stu1 >= stu2) // true
print(stu1 >= stu3) // true
print(stu1 <= stu3) // true
print(stu2 < stu1) // true
print(stu2 <= stu1) // true
}
自定义运算符使用
/// 二、自定义运算符使用
/**
可以自定义新的运算符:在全局作用域使用operator进行声明
*/
prefix operator +++
postfix operator +++
infix operator +- : PlusMinusPrecedence
precedencegroup PlusMinusPrecedence{
associativity:left //left right none none只允许两个变量做运算 否则会报错
higherThan:AdditionPrecedence
lowerThan:MultiplicationPrecedence
assignment:true //true代表在可选链操作中拥有跟赋值运算符一样的优先级 person?.age = 10 person?.age +- Point(1,1) 及person解包失败是 后边就不再进行
}
struct CustomPoint {
var x:Int
var y:Int
init(x:Int,y:Int){
self.x = x
self.y = y
}
static prefix func +++ (p1:inout CustomPoint)->CustomPoint{
p1.x+=2
p1.y+=2
return p1
}
static postfix func +++ (p1:inout CustomPoint)->CustomPoint{
let temp = p1
p1.x+=2
p1.y+=2
return temp
}
static func +- (p1:CustomPoint,p2:CustomPoint)->CustomPoint{
CustomPoint(x:p1.x + p2.x , y:p1.y - p2.y)
}
}
func customOperatorUse() -> Void {
var cp = CustomPoint(x: 1, y: 1)
print(+++cp)
print(cp)
print(cp+++)
print(cp)
let cp1 = CustomPoint(x: 10, y: 10)
let cp2 = CustomPoint(x: 20, y: 20)
print(cp1 +- cp2)
}
extension的使用
/// 三、extension的使用
/**
Swift中的扩展,有点类似于OC中的分类(Category)
扩展可以为枚举、结构体、类、协议添加新功能
可以添加方法、计算属性、下标、(便捷)初始化器、嵌套类型、协议等等
扩展不能办到的事情
不能覆盖原有的功能
不能添加存储属性,不能向已有的属性添加属性观察器
不能添加父类
不能添加指定初始化器,不能添加反初始化器
...
*/
//1、扩展Double类型
extension Double {
var km: Double { self * 1_000.0 }
var m: Double { self }
var dm: Double { self / 10.0 }
var cm: Double { self / 100.0 }
var mm: Double { self / 1_000.0 }
}
func extensionUse1 () {
let d = 20.0
print(d.km)//20000.0
}
//2、扩展Int类型
extension Int {
func repetitions(task: () -> Void) {
for _ in 0..<self {
task()
}
}
mutating func square() -> Int {
self = self * self
return self
}
enum Kind { case negative, zero, positive }
var kind: Kind {
switch self {
case 0:
return .zero
case let x where x > 0:
return .positive
default:
return .negative
}
}
subscript(digitIndex: Int) -> Int {
var decimalBase = 1
for _ in 0..<digitIndex {
decimalBase *= 10
}
return (self / decimalBase) % 10
}
}
func extensionUse2 () {
let i = 2
i.repetitions {
print("i = ",i)//
}
print(i.kind)//positive
}
//3、扩展Array类型
extension Array {
subscript(nullable idx: Int) -> Element? {
if (startIndex..<endIndex).contains(idx) {
return self[idx]
}
return nil
}
}
func extensionUse3() -> Void {
let arr = [1,2,3]
print(arr[0])//1
if let num = arr[nullable:0] {
print(num)//1
}else{
print("越界")
}
if let num = arr[nullable:0-1] {
print(num)
}else{
print("越界")//越界
}
}
//4、泛型,扩展中依然可以使用原类型中的泛型类型
class Stack<E> {
var elements = [E]()
func push(_ element: E) {
elements.append(element)
}
func pop() -> E {
elements.removeLast()
}
func size() -> Int {
elements.count
}
}
extension Stack {
// 扩展中依然可以使用原类型中的泛型类型
func top() -> E { elements.last! }
}
// 符合条件才扩展
extension Stack : Equatable where E : Equatable {
static func == (left: Stack, right: Stack) -> Bool {
left.elements == right.elements
}
}
func extensionUse4(){
let sta1:Stack = Stack<Int>()
let sta2:Stack<Int> = Stack<Int>()
let sta3:Stack<Int> = sta1
sta1.push(8)
print(sta1.top()+2)//10
print(sta1 == sta2)//false
print(sta1 == sta3)//true
}
//5、通过扩展添加自定义初始化器,能做到保留编译器生成的默认初始化器
/**
如果希望自定义初始化器的同时,编译器也能够生成默认初始化器
可以在扩展中编写自定义初始化器
required初始化器也不能写在扩展中
*/
struct LCPoint {
var x:Int = 0
var y:Int = 0
}
extension LCPoint {
//通过扩展添加了自定义初始化器,但编译器生成初始化器仍然可用
init(point:LCPoint) {
self.x = point.x
self.y = point.y
}
//required初始化器也不能写在扩展中
//'required' initializer in non-class type 'LCPoint'
//required init(p:(Int,Int)){
init(_ p:(Int,Int)){
self.x = p.0
self.y = p.1
}
}
extension LCPoint : Equatable{
static func ==(lv:LCPoint,rv:LCPoint) -> Bool {
(lv.x,lv.y) == (rv.x,rv.y)
}
}
func extensionUse5() -> Void {
let point1 = LCPoint(x: 10, y: 20)
let point2 = LCPoint(point: point1)
let point3 = LCPoint((10,20))
print(point1,point2,point3)// LCPoint(x: 10, y: 20) LCPoint(x: 10, y: 20) LCPoint(x: 10, y: 20)
print(point1 == point2)// true
print(point1 == point3)// true
}
//6、扩展协议
struct LCTest {
var x:Int = 0
var y:Int = 0
func test1() -> Void {
print("func test1")
}
func test2() -> Void {
print("func test2")
}
func test3() -> Void {
print("func test3")
}
}
protocol LCTestProtocol {
func test1() -> Void
func test2() -> Void
}
/**
如果一个类型已经实现了协议的所有要求,但是还没有声明它遵守了这个协议
可以通过扩展来让它遵守这个协议
*/
extension LCTest : LCTestProtocol{}
/**
扩展可以给协议提供默认实现,也间接实现『可选协议』的效果
扩展可以给协议扩充『协议中从未声明过的方法
*/
extension LCTestProtocol {
//在协议的扩展中添加的方法必须实现,作为默认实现
//这样遵从这个协议的类,就可以不实现这个方法
func test3() -> Void {
print("test3")
}
}
extension BinaryInteger {
//提供默认实现
func isOdd() -> Bool { self % 2 != 0 }
}
func extensionUse6() -> Void {
//1、查看某个类是否遵守了某个协议
do{
print("--------1--------")
let test = LCTest()
print(test is LCTestProtocol)//true
}
//2、提供默认实现
do{
print("---------2----------")
LCTest().test3() //test3
print( 2.isOdd()) //false
}
}
行者常至,为者常成!