本文会展示一个swift 4.1编译器的疑似Bug。跟泛型协议有关。
感觉swift还是有很长的路要走.
事实上,就国内网络上关于swift的资料真的不多,swfit泛型,协议相关的更是冷门。
最经典的一个问题是为什么协议泛型的写法(associatedtype T)和泛型类(<T>)的写法不同。这个例子也可以侧面证明下它们的区别。
需求略微复制,正好测试下协议约束。定义一个my type。约束是X==Y
约束说明
把它形象化一点是这样的
类型相关的概念有:[老师,科目,学院,大学,实验室]
学院有老师,老师有TA研究的科目
大学不仅具备学院的功能(有老师),还有它的实验室,实验室里也有老师
约束要求大学的老师和实验室的老师是同一种科目的老师
下面swift的代码在4.1环境中
如果把 '大学'的定义挪到最后,则无法编译通过,这在其他编程语言里太难理解
特定情况才发生编译失败的代码如下
//如果把 '大学'的定义挪到最后,则无法编译通过
//老师,Subject = 科目
public class Teacher<Subject> {
}
//大学
public protocol University : College {
associatedtype L where L:Lib,L.S == S, L.K == K
//associatedtype L : Lib where L.S == S,L.K == K //这样写任何位置都无法编译通过
var seniorLib:L {get set} //高级实验室
}
//学院
public protocol College {
associatedtype K : Teacher<S>
associatedtype S
var mainSubject:S {get set}
}
//实验室
public protocol Lib {
associatedtype K : Teacher<S>
associatedtype S
var mainSubject:S {get set}
}
破解这个编译问题的一个方法,当然是更好是利用swift的风格来实现。
简单说就放弃泛型类,用泛型协议来定义老师这个类型。把泛型类参数Subject变为协议关联类
public class Teacher<Subject>
改为
public protocol XTeacher {
associatedtype Subject
}
剩下就可以简化泛型参数,最后大学类型的定义无论放在哪个位置 swift 4.1下均不会编译报错
用一张图来对比修改更清晰明了,不再赘述。
修复后编译成功的代码如下
//如果把 '大学'的定义挪到任何位置都可以编译通过
//老师,Subject = 科目
public protocol XTeacher {
associatedtype Subject
}
//大学
public protocol XUniversity : XCollege {
associatedtype L where L:XLib, L.K == K
//associatedtype L:XLib where L.K == K //这样写也不会报错
var seniorLib: L {get set} //高级实验室
}
//学院
public protocol XCollege {
associatedtype K : XTeacher
var mainSubject:K.Subject {get set}
}
//实验室
public protocol XLib {
associatedtype K : XTeacher
var mainSubject:K.Subject {get set}
}
网友评论