swift学习笔记->泛型

如果学过java就知道泛型是什么  比如说定义一个数组  var a : [Int]

Int 就是该数组的泛型 创建一个字典也是根据泛型储存内容的

var a : Dictionary <String,String>

而泛型能解决的问题  就像字典一样  他是个不确定的键值对  你定义什么类型就能存什么类型

泛型函数

下面举个例子一个函数  要将两个参数值互换

func  myswap(inout a: Int,inout b: Int) {
    let temp  = a
    a = b
    b = temp  
}

如上所写   只能交换int类型数据   如果要String类型呢    是不是又要另外写一份?

这里用泛型就省力了   把参数类型改成未知的一个泛型一般用 "T"

func  myswap<T>(inout a: T,inout b: T) {
    let temp  = a
    a = b
    b = temp
}

语法就不多解释了  尖括号写的是泛型  形参用就可以了

这样只要满足运算符"="操作的类型就能交换

泛型类型

在类或结构中定义一个泛型类型    下面举个栗子

class Stack<Element> {
    var containers = [Element]()
     func push(e: Element) {
        containers.append(e)
    }
     func pop() -> Element {
        return containers.removeLast()
    }
}

var data: Stack<Int> = Stack<Int>()

这个类是模仿栈的结构有push入栈与pop出栈两个方法

类中的数组在类实例化时决定

泛型扩展

扩展时,不需要再指定泛型参数(尖括号里面的内容称之为泛型参数)

extension Stack {
    var count: Int {
        return containers.count
    }  
  func aa(e:Element){    print(e)  }
} var data2 = Stack<String>() data2.push("dasdf") data2.count

泛型约束

你可以写一个在一个类型参数名后面的类型约束,通过冒号分割,来作为类型参数链的一部分。这种作用于泛型函数的类型约束的基础语法如下所示(和泛型类型的语法相同):

func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
    // function body goes here
}

上面这个假定函数有两个类型参数。第一个类型参数T,有一个需要T必须是SomeClass子类的类型约束;第二个类型参数U,有一个需要U必须遵循SomeProtocol协议的类型约束。

用处也跟泛型函数类似  比如写一个查找数组中是否有该数  有则返回下标  没有则返回-1

func index<T:Equatable>(arr:[T],data: T) ->Int {
    for (m,n) in arr.enumerate() {
        if n == data  {
            return m
        }
    }
    return -1
}

这样写也就意味着“任何T类型都遵循Equatable协议”   如果有多个需要约束的协议则在Eqatableh

where T:类型,T:类型....

协议的关联类型修饰符  typealias

  定义协议时我们无法声明泛型  所以在协议中泛型写法变了一下

protocol Containter {
    typealias Element
    mutating func push(e: Element)
    mutating func pop()-> Element
}

实现该协议

struct MyStack: Containter{
    //   typealias Element = Int

    var containers = [Int]()
    mutating func push(e: Int) {
        containers.append(e)
    }
    mutating func pop() -> Int {
        return containers.removeLast()
    }
}

实现时经过swift类型推断 实现为 Element = Int

实现后更改泛型名称也是可以的

struct Stack<Element,Com>: Containter {
    //按照当前的实现,下面的代码由于类型推断,可以省略
    //typealias Element = E
    var containers = [Element]()
    var com=[Com]()
    mutating func push(e: Element) {
        containers.append(e)
    }
    mutating func pop() -> Element {
        return containers.removeLast()
    }

}

扩展协议时的约束以及协议关联类型的使用

//定义两个协议MM,NN
protocol MM {

}
protocol NN : MM{

}
//分别实现协议MMClass,NNClass
class MMClass: MM {

}
class NNClass: NN {

}
//定义f泛型协议Container
protocol Container {
    typealias ItemType
}
//扩展泛型协议Container的泛型  使其受MM协议约束
extension Container where   ItemType: MM {
    var b: Int {return 5}
}
//扩展泛型协议Container的泛型  使其受NN协议约束
extension Container where   ItemType: NN {
    var b: Int {return 6}
}
//TestTest类实现Container协议
class TestTest: Container {
    typealias ItemType = MMClass //如果这里改为MMClass,那么aaaa.b输出结构是5
}
class TestTest2: Container {
    typealias ItemType = Int //若泛型类型的值不满足任何一个协议则无法访问b属性
}
let aaaa  = TestTest()
aaaa.b
let bbbb = TestTest2()
bbbb.b//报错
时间: 2024-12-13 01:54:51

swift学习笔记->泛型的相关文章

SWIFT学习笔记04

1.在实际编译时,Swift 编译器会优化字符串的使用,使实际的复制只发生在绝对必要的情况下,这意味着您将字符串作为值类型的同时可以获得极高的性能. 2.for character in "Dog!" { println(character) } // D // o // g // ! 3.通过标明一个Character类型注解并通过字符字面量进行赋值,可以建立一个独立的字符常量或变量: let yenSign: Character = "¥" 4.计算字符数量 l

SWIFT学习笔记05

1.Swift 无需写break,所以不会发生这种贯穿(fallthrough)的情况.2.//用不到变量名,可用"_"替换 for _ in 1...power { answer *= base } 3.case 可以匹配更多的类型模式,包括区间匹配(range matching),元组(tuple)和特定类型的描述. 可以这样用case case 1...3: naturalCount = "a few" 4.如果存在多个匹配,那么只会执行第一个被匹配到的 ca

SWIFT学习笔记02

1.//下面的这些浮点字面量都等于十进制的12.1875: let decimalDouble = 12.1875 let exponentDouble = 1.21875e1 let hexadecimalDouble = 0xC.3p0//==12+3*(1/16) 2.//类型别名,用typealias关键字来定义类型别名 typealias AudioSample = UInt16 var maxAmplitudeFound = AudioSample.min 3.//元组 let ht

swift学习笔记(三)关于拷贝和引用

在swift提供的基本数据类型中,包括Int ,Float,Double,String,Enumeration,Structure,Dictionary都属于值拷贝类型. 闭包和函数同属引用类型 捕获则为拷贝.捕获即定义这些常量和变量的原作用域已不存在,闭包仍然可以在闭包函数体内引用和修改这些值 class属于引用类型. Array的情况稍微复杂一些,下面主要对集合类型进行分析: 一.关于Dictionary:无论何时将一个字典实例赋给一个常量,或者传递给一个函数方法时,在赋值或调用发生时,都会

Swift学习笔记十二:下标脚本(subscript)

下标脚本就是对一个东西通过索引,快速取值的一种语法,例如数组的a[0].这就是一个下标脚本.通过索引0来快速取值.在Swift中,我们可以对类(Class).结构体(structure)和枚举(enumeration)中自己定义下标脚本的语法 一.常规定义 class Student{ var scores:Int[] = Array(count:5,repeatedValue:0) subscript(index:Int) -> Int{ get{ return scores[index];

Swift学习笔记四:数组和字典

最近一个月都在专心做unity3d的斗地主游戏,从早到晚,最后总算是搞出来了,其中的心酸只有自己知道.最近才有功夫闲下来,还是学习学习之前的老本行--asp.net,现在用.net做项目流行MVC,而不是之前的三层,既然技术在更新,只能不断学习,以适应新的技术潮流! 创建MVC工程 1.打开Visual studio2012,新建MVC4工程 2.选择工程属性,创建MVC工程 3.生成工程的目录 App_Start:启动文件的配置信息,包括很重要的RouteConfig路由注册信息 Conten

Swift学习笔记(二)参数类型

关于参数类型,在以前的编程过程中,很多时间都忽视了形参与实参的区别.通过这两天的学习,算是捡回了漏掉的知识. 在swift中,参数有形参和实参之分,形参即只能在函数内部调用的参数,默认是不能修改的,如果想要修改就需要在参数前添加var声明. 但这样的声明过后,仍旧不会改变实参的值,这样就要用到inout了,传递给inout的参数类型必须是var类型的,不能是let类型或者字面类型,(字面类型是在swift中常提的一个术语,个人认为就是赋值语句,也不能修改)而且在传递过程中,要用传值符号"&

Swift学习笔记十:属性

1.存储属性       1. 作为特定类或结构实例的一部分,存储属性存储着常量或者变量的值.存储属性可分为变量存储属性(关键字var描述)和常量存储属性(关键字let描述). struct student{ let name = "" var score = 0 } let a = student(name:"小笨狼",score:96)           注意:                ① 定义储存属性时,需要为每一个属性定义一个默认值.在初始化的时候,

Swift学习笔记(4)--字符串及基本使用

String是例如"hello, world","海贼王" 这样的有序的Character(字符)类型的值的集合,通过String类型来表示. Swift 的String类型与 Foundation NSString类进行了无缝桥接.如果您利用 Cocoa 或 Cocoa Touch 中的 Foundation 框架进行工作.所有NSString API 都可以调用您创建的任意String类型的值.除此之外,还可以使用本章介绍的String特性.您也可以在任意要求传