swift泛型

简单的

// protocol
// 搞不懂为嘛不使用Flier<T>,而要多使用一个关键字associatedtype
// 注: associatedtype是swift2.2新引入的关键字, 先前为typealias
protocol Flier {
    associatedtype T
    func flyWith(f: T)
    func mateWith(f: T)
    func shitWith(f: Self) //Self表示将要实现这个接口的那个`类`的类型
    
}
// 实现接口
class Bird: Flier {
    func flyWith(f: String) {}
    func mateWith(f: String) {}
    func shitWith(f: Bird) {}
}

// 函数
func takeAndReturn<T>(t: T) -> T {
    return t
}

takeAndReturn("hello")
takeANdReturn(2)

// 结构体
struct HolderOfTwoSame<T> {
    var v1: T
    var v2: T
}
HolderOfTwoSame(v1: "hello", v2: "world")

// 类
class Animal<T> {
    func playWith(t: T) {
        print("I am playing with: \(t)")
    }
}

// 继承自指定了具体的泛型类型的Animal
class Dog: Animal<String> {}

// 继承自泛型的Animal
class AnotherDog<T>: Animal<T> {
    override func playWith(t: T) {
        print("I played with: \(t)")
    }
}

var animal = Animal<Int>()
animal.playWith(2)

var d = Dog();
d.playWith("only string allowed here")

var dd = AnotherDog<String>()
dd.playWith("xiaohua")

多个泛型参数

// protocol
// 搞不懂为嘛不使用Flier<A,B>,而要多使用一个关键字associatedtype?
protocol Flier {
    associatedtype A
    associatedtype B
    func flyWith(f: A)
    func mateWith(f: B)
    func shitWith(f: Self) //Self表示将要实现这个接口的那个`类`的类型
    
}

class Bird: Flier {
    func flyWith(f: String) {}
    func mateWith(f: String) {}
    func shitWith(f: Bird) {}
}

// func
func takeAndReturn<A,B>(v1: A, v2: B) -> (A,B) {
    return (v1, v2)
}

takeAndReturn("hello", v2: 2)


// struct
struct HolderOfTwoType<A, B> {
    var v1: A
    var v2: B
}
HolderOfTwoType(v1: "hello", v2: "world")

// class
class Animal<A,B> {
    func playWith(t: A, and: B) {
        print("I am playing with: \(t) and \(and)")
    }
}

class Dog: Animal<String, Int> {}

var animal = Animal<Int, String>()
animal.playWith(2, and: "Alice")

var d = Dog();
d.playWith("only string allowed here", and: 3)

带类型约束的(protocol)

// 第一版
// protocol
protocol Flier {
    func flyWith(f: Flier)
    
}

class Bird: Flier {
    // 这里只能和protocol保持一致,声明为Flier,
    // 声明为Bird就会报错, (怎么能在这里定义成Bird, 见下面)
    func flyWith(f: Flier) {}
}

class ButterFly: Flier{
    func flyWith(f: Flier){}
}


var b1 = Bird()
var b2 = ButterFly()
b1.flyWith(b2)

// 以下是第二版
// protocol
protocol SuperFlier {}
protocol Flier: SuperFlier {
    // error: type may not reference itself as a requirement
    // associatedtype T: Flier
    
    associatedtype T: SuperFlier
    
    // 可以用一个类型为Flier的占位符放在这里
    // 但是蛋疼的是, 不能使用接口自身做为占位符
    // 所以这里定义了一个什么都不干的SuperFlier以此满足compiler的要求
    func flyWith(f: T)
    
}

class Bird: Flier {
    // 然后就可以在这里使用Bird
    func flyWith(f: Bird) {}
}

var b1 = Bird()
b1.flyWith(b1)

带类型约束的(func)


// 出现了Self或associatedtype关键字的protocol叫做generic protocol
// generic protocol不能直接放在参数列表中, 只能做为类型约束(出现在尖括号里)
protocol Flier {
    associatedtype T
    func flyWith(f: T)
    
}

// 注意这里的Bird并没有实现该generic protocol, 只是使用了(依赖)Flier
class Bird{
    // error: protocol 'Flier' can only be used as a generic constraint because it has Self or associated type requirements
    //func flyWith(f: Flier) {}
    
    // 上面这行代码出错, 应该改为
    func flyWith<T: Flier>(f: T) {}

}


// eg2: 函数体中的小于号要求这里的泛型参数必须是Comparable类型的
func myMin<T: Comparable>(things: T...) -> T {
    var minimum = things[0]
    for ix in 1..<things.count {
        if things[ix] < minimum {
            minimum = things[ix]
        }
    }
    return minimum
}

待续
阅读[What do you really know about typealias and associatedtype?]

在实现中指定泛型类型的几种方式
 

// 接口如下
protocol IAnimal {
    associatedtype T = Double // 其中 = Double是指定它的默认实现类型, 可以去掉
    func playWith(t: T)
}


class Cat : IAnimal {
    // 1. 通过typealias指定associatedtype的具体类型
    typealias T = String
    
    func playWith(t: T) {
        print("I played with: \(t)")
    }

}

// 2. 通过尖括号指定associatedtype的具体类型
class AnotherCat<T> : IAnimal {
    func playWith(t: T) {
        print("I played with: \(t)")
    }
    
}

// 3. 通过尖括号指定associatedtype的具体类型(带类型约束)
class YetAnotherCat<T: IAnimal> : IAnimal {
    
    func playWith(t: T) {
        print("I played with: \(t)")
    }
    
}


var cat1 = Cat()
cat1.playWith("meow")

var cat2 = AnotherCat<Int>()
cat2.playWith(2)

var cat3 = YetAnotherCat<Cat>()
cat3.playWith(cat1)

待续

转载于:https://my.oschina.net/uniquejava/blog/683774

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值