iOS — 扩展和泛型(swift)
下面简单的介绍扩展和泛型的应用
扩展基础
嵌套类型
扩展标准库
泛型函数
泛型类型
一:扩展基础
struct Point{
var x = 0.0
var y = 0.0
}
struct Size{
var width = 0.0
var height = 0.0
}
class Rectangle{
var origin = Point()
var size = Size()
init( origin: Point , size: Size ){
self.origin = origin
self.size = size
}
}
// extension 中放入新的方法
extension Rectangle{//类的扩展中只能扩展方法,计算型属性和convenience的init方法,而类型的存储属性和init方法只能写在类中,这就是扩展,帮助开发者实现多人开发
// 如果是struct,就需要使用mutating关键字
func translate(x x: Double, y: Double){
self.origin.x += x
self.origin.y += y
}
}
let rect = Rectangle(origin: Point(), size: Size(width: 4, height: 3))
rect.translate(x: 10, y: 10)
rect
// extension 中放入新的属性
extension Rectangle{
// extension中只能放入计算型属性
var center: Point{
get{
let centerX = origin.x + size.width/2
let centerY = origin.y + size.height/2
return Point(x: centerX, y: centerY)
}
set(newCenter){
origin.x = newCenter.x - size.width/2
origin.y = newCenter.y - size.height/2
}
}
var area: Double{
return size.width * size.height
}
var perimeter: Double{
return 2*(size.width + size.height)
}
// 可以在extension中根据计算性属性放入新的构造函数
// extension中只能放入convenience的构造函数
convenience init(center: Point, size: Size){
let originX = center.x - size.width/2
let originY = center.y - size.height/2
//self.origin = Point(x: originX, y: originY)
//self.size = size
self.init(origin: Point(x: originX, y: originY), size: size)
}
}
rect.area
rect.perimeter
rect
let rect2 = Rectangle(center: Point(), size: Size(width: 6, height: 8))
rect2
二:嵌套类型
//nested type
class UI{
enum Theme{
case DayMode
case NightMode
}
var fontColor: UIColor!
var backgroundColor: UIColor!
var themeMode: Theme = .DayMode{
didSet{
self.changeTheme(self.themeMode)
}
}
init(){
self.themeMode = .DayMode
self.changeTheme(self.themeMode)
}
init(themeMode: Theme){
self.themeMode = themeMode
self.changeTheme(themeMode)
}
func changeTheme( themeMode: Theme ){
switch(themeMode){
case .DayMode:
fontColor = UIColor.blackColor()
backgroundColor = UIColor.whiteColor()
case .NightMode:
fontColor = UIColor.whiteColor()
backgroundColor = UIColor.blackColor()
}
}
}
let ui = UI()
ui.themeMode
ui.fontColor
ui.backgroundColor
ui.themeMode = .NightMode
ui.themeMode
ui.fontColor
ui.backgroundColor
// 以前就见过Nest Type这个就是一个嵌套的枚举类型,Index就是定义在string类里面的类型
// String.Index
let str = "Hello World"
let index = str.startIndex.advancedBy(5)
str.substringToIndex(index)
//
struct Point{
var x = 0.0
var y = 0.0
}
struct Size{
var width = 0.0
var height = 0.0
}
class Rectangle{
var origin = Point()
var size = Size()
init( origin: Point , size: Size ){
self.origin = origin
self.size = size
}
}
// extension 中放入 Nested Type, Methods 和 subscript
extension Rectangle{
// extension 中放入 Nested Type
enum Vertex: Int{
case LeftTop
case RightTop
case RightBottom
case LeftBottom
}
func pointAtVertex( v: Vertex ) -> Point{
switch v{
case .LeftTop:
return origin
case .RightTop:
return Point(x: origin.x + size.width, y: origin.y )
case .RightBottom:
return Point(x: origin.x + size.width, y: origin.y + size.height )
case .LeftBottom:
return Point(x: origin.x, y: origin.y + size.height )
}
}
// extension 中放入 subscript
subscript(index: Int) -> Point{
//assert的功能在于:如果index参数不满足条件,那么就会打印出Index in Rectange Out of Range.
assert( index >= 0 && index < 4 , "Index in Rectange Out of Range.")
return pointAtVertex(Vertex(rawValue: index)!)
}
}
let rect = Rectangle(origin: Point(), size: Size(width: 4, height: 3))
rect.pointAtVertex(.RightBottom)
rect[0]
rect[1]
rect[2]
rect[3]
三:扩展标准库
extension Int{
var square: Int{//扩充标准库的计算属性
return self*self
}
var cube: Int{
return self*self*self
}
//扩充方法
func inRange(closedLeft left: Int, openedRight: Int) -> Bool{
return self >= left && self < openedRight
}
//这里的参数的类型是个函数
func repetitions(task: () -> Void ){
for _ in 0..<self{
task()
}
}
func stride(to end: Int, by stride: Int, task: (Int) -> Void ){
for i in self.stride(to: end, by: stride){
task(i)
}
}
}
let num = 8
num.square
let str = "Hello, Swift"
let index = 21
index.inRange(closedLeft: 0, openedRight: str.characters.count)
10.repetitions{
print("Hello, Swift")
}
for i in 2.stride(to: 10, by: 2){
print(i)
}
for i in 2.stride(through: 10, by: 2){
print(i)
}
2.stride(to: 10, by: 2){ num in
print(num*num)
}
// Int还有很多可以做enxtension的地方
// 如 12345[2]
// 如 toBinary, toHex
// 如 isPrime
// extension在App开发中被经常使用
// 如 String, UIColor等基础类的使用
// 在App开发中, 一个界面可能需要处理多个事件: 表格显示, 用户输入, 导航, 动画, 数据存储...
// 此时可以使用extension分隔开
四:泛型函数
func swapTwoInt(inout a: Int , inout _ b: Int){//这里的inout关键字表面:参数的传递是按照引用传递的
(a,b) = (b,a)
}
var a: Int = 0
var b: Int = 6
swapTwoInt(&a, &b)
a
b
func swapTwoDouble(inout a: Double , inout _ b: Double){
(a,b) = (b,a)
}
// 使用generic
// generic function(泛型函数):前面两个函数的意思其实是一样的,就是交换两个参数的值,只是类型不一样,这样做产生了冗余的代码,下面这个swapTwoThings函数为我们引出了泛型的概念,<T>:表示这个函数的参数的类型是T,那么无论我们传入的是int类型的参数还是string类型,只要定义了这个泛型函数的逻辑,传入参数的任意类型都能使用这个逻辑,扩展了函数的通用性
func swapTwoThings<T>(inout a: T , inout _ b: T){
(a,b) = (b,a)
}
var hello = "Hello"
var bye = "Bye"
swapTwoThings(&hello, &bye)
hello
bye
swapTwoThings(&a, &b)
a
b
swap(&a, &b)
五:泛型类型
// generic type
let arr = Array<Int>()
let dict = Dictionary<String,Int>()
let set = Set<Float>()
//注意:一个空数组的声明有两种写法,利用inference可以知道aaa和b的数据类型是个数组
let aaa = [Int]()
let b = Array<Int>()
struct Stack<T>{//<T>表示stack里面的数据类型是任意的
var items = [T]()//在这里声明一个T类型的数组
// //当然声明一个空数组也可以这样写:
// var items1:Array<T> = [T]()
//
// //或者这么写
// var items2:Array<T> = Array<T>()
func isEmpty() -> Bool{//返回值为bool类型的函数,用来判断数组是否为空
return items.count == 0
}
mutating func push(item: T){//由于stack是一个结构体,这个push函数改变了结构体中的数据,那么应该使用mutating关键字
items.append(item)
}
mutating func pop() -> T?{
guard !self.isEmpty() else{
return nil
}
return items.removeLast()
}
}
extension Stack{
func top() -> T?{
return items.last
}
func count() -> Int{
return items.count
}
}
var s = Stack<Int>()
s.push(1)
s.push(2)
s.pop()
var ss = Stack<String>()
struct Pair<T1,T2>{//通过字典引出结构体中可以拥有两个泛型的数据类型
var a: T1
var b: T2
}
var pair = Pair<Int,String>(a: 0 , b: "Hello")
pair.a
pair.b