swift4.1 系統學習二十一 泛型
/*
泛型
本節我們一起學習泛型這一概念。在專案中,多次用到了泛型,但是對它的理解總是不夠透徹,運用也不熟練。
趁此機會,好好熟悉一下。
什麼是泛型?
比如我們要實現一種演算法,例如搜尋、排序等,相對於傳統C語言,如果我們要針對不同的型別實現相同的演算法,‘
每種資料型別都要寫一遍,顯得乏味而又冗餘。這個時候我們就可以使用泛型,提供一種演算法的實現函式,然後
在呼叫此函式的時候在確定相關資料的型別就可以了。
*/
print("---------泛型的概念--------------")
struct A {
/*
這裡定義了函式calculate
其泛型遵循了BinaryInteger協議。
*/
static func calculate<T: BinaryInteger> (a: T, b: T) -> T {
return a * a + b * b
}
static func calculate<T: FloatingPoint> (a: T, b: T) -> T {
return a * a + b * b
}
}
do {
let i = A.calculate(a: 3, b: 4)
print("i = \(i)")
let j = A.calculate(a: 3.0, b: 4.0)
print("j = \(j)")
}
/*
小結:
通過上面的例子可以看出來,使用泛型之後,函式定義一下子簡單了。我們不僅可以使用Int8,Int16,Int32
等整數型別,還可以使用Float、Double等浮點型別。如果沒有泛型,那麼我們要寫10多種函式實現,
是不是簡化了很多呢?
*/
// 1. 泛型基本使用
/*
swift 中,我們可以對函式以及方法使用泛型,但是不能用於閉包,不能用於協議。
無論是對函式還是對型別使用泛型,我們均可以在函式或者型別識別符號後面跟 <>,裡面放泛型形參列表。
*/
do {
// 定義一個泛型結構體,泛型形參為T
struct MyStruct<T> {
/// 用泛型T定義儲存成員t
var t: T
/// 定義一個例項方法,其引數也是泛型T
mutating func method(value: T) {
t = value
print("new value = \(value)")
}
/// 定義型別方法swap,是一個泛型方法,泛型形參為E
static func swap<E>(a: inout E, b: inout E) {
let tmp = a
a = b
b = tmp
}
}
/*
將MyStruct型別特化為MyStruct<Int32>,表示其泛型實參為Int32型別。
*/
var st = MyStruct<Int32>(t: 100)
// 呼叫method方法
st.method(value: 200)
// 這裡預設<Int32>,此時MyStruct將被型別推導為MyStruct<Int>。
var ss = MyStruct(t: 100)
ss.method(value: 200)
var a = 10, b = 20
// 這裡呼叫了MyStruct的swap型別方法,
// 並且其泛型被推導為Int型別。
// 這裡注意,即便我們沒有直接使用MyStruct物件例項,
// 但依然需要對MyStruct做泛型特化,
// 由於這裡不需要做特殊處理,
// 所以對MyStruct直接指定空元組即可。
MyStruct<()>.swap(a: &a, b: &b)
print("a = \(a), b = \(b)")
var x = 0.5, y = 5.0
MyStruct<()>.swap(a: &x, b: &y)
print("x = \(x), y = \(y)")
var c = 100, d = 200
MyStruct<Int>.swap(a: &c, b: &d)
print("c = \(c), d = \(d)")
var e = "a", f = "b"
MyStruct<String>.swap(a: &e, b: &f)
print("e = \(e), b = \(f)")
var arr1 = [1, 2, 3]
var arr2 = [10, 20, 30, 40]
MyStruct<[Int]>.swap(a: &arr1, b: &arr2)
print("arr1 = \(arr1), arr2 = \(arr2)")
}
/*
小結:
上述程式碼可以看出,泛型是多麼方便啊。對於交換兩個物件的值,我們只需要使用泛型,就可以寫一種演算法,針對
各個型別都可以使用了。
*/
/*
對於函式以及方法的泛型特化,我們不能顯示指定泛型實參,只能通過推導得出。
如果某一函式只有返回型別是一個泛型型別,那麼呼叫它的時候,必須顯式提供左值型別。
*/
do {
func foo<T: SignedInteger>() -> T {
return T()
}
let a: Int16 = foo()
print("a = \(a)")
}
// 2. 型別約束
/*
swift中引入了泛型的“型別約束”,用於說明當前泛型型別必須遵循哪些協議,或者繼承自哪個類。有了這個
設定之後,我們的泛型的靈活性就大大增強了。
*/
do {
print("\n--------2. 型別約束-----------\n")
// 定義了一個泛型函式,必須遵循Comparable協議
func foo<T: Comparable>(a: T, b: T, c:T) {
var minValue = min(a, b)
minValue = min(minValue, c)
var maxValue = max(a, b)
maxValue = max(maxValue, c)
let range = minValue ... maxValue
print("the range is : \(range)")
}
foo(a: 10, b: 30, c: 20)
}
// 3. 泛型where從句
/*
有時我們在一個結構體或類中遵循了帶有關聯型別的協議,此時我們想實現一個泛型型別或泛型函式,使得該泛型遵循該協議,並且對該協議的泛型進行約束,那麼我們可以使用Swift中的where從句來實現。
*/
protocol Prot {
// 這裡定義一個關聯型別,相當於協議中的泛型
associatedtype ArgType
func method(obj: ArgType)
}
do {
print("\n-----------3. 泛型where從句---------------\n")
struct MyStruct: Prot {
typealias ArgType = Int
func method(obj: Int) {
print("obj = \(obj)")
}
}
/*
這裡定義了泛型結構體Test,其泛型T遵循了Prot協議,使用where語句用來約束Prot協議中關聯型別
必須遵循Comparable協議。
*/
struct Test<T: Prot> where T.ArgType: Comparable {
func method<E: Prot>(e: E) where E.ArgType == Int {
print("e = \(e)")
e.method(obj: 100)
}
}
let test = Test<MyStruct>()
test.method(e: MyStruct())
}
// 4. swift4.0之後對泛型特徵的補充
/*
swift 4.0之後,我們允許對下標使用泛型。
*/
do {
print("\n-----------4. swift4.0之後對泛型特徵的補充------------\n")
struct Test {
subscript<T: FixedWidthInteger>(index: T) -> T {
return index + T(1)
}
}
let a = Test()[Int8(10)]
print("a = \(a), a type is: \(type(of: a))")
let b = Test()[UInt16(600)]
print("b = \(b), b type is: \(type(of: b))")
}
相關文章
- C#學習 [型別系統] 泛型(16)C#型別泛型
- 系統學習NLP(二十一)--SWEM
- C#泛型學習C#泛型
- 泛型學習筆記泛型筆記
- java泛型學習(1)Java泛型
- 泛型類及系統中常用的泛型類泛型
- 學習Rust泛型與特性Rust泛型
- TypeScript學習(四)—— 介面和泛型TypeScript泛型
- rust學習十一.1、泛型(通用型別)Rust泛型型別
- java入門基礎學習----泛型Java泛型
- java基礎學習之十三:泛型Java泛型
- 深圳大資料學習:泛型--【千鋒】大資料泛型
- iOS學習筆記47 Swift(七)泛型iOS筆記Swift泛型
- 推薦系統遇上深度學習(二十一)--階段性回顧深度學習
- Java泛型複習Java泛型
- JAVA泛型使用練習2(自定義泛型使用)Java泛型
- 泛型粒子系統的設計1 (轉)泛型
- 泛型粒子系統的設計2 (轉)泛型
- 泛型粒子系統的設計3 (轉)泛型
- 泛型粒子系統的設計4 (轉)泛型
- 泛型粒子系統的設計5 (轉)泛型
- 泛型粒子系統的設計6 (轉)泛型
- 泛型粒子系統的設計7 (轉)泛型
- Java進階學習之集合與泛型(1)Java泛型
- Java隨筆-Java泛型的一點學習Java泛型
- Java高階特性之泛型學習總結Java泛型
- JDK5.0新特性的學習--泛型(下)JDK泛型
- JDK5.0新特性的學習--泛型(上)JDK泛型
- Dart語法篇之型別系統與泛型(七)Dart型別泛型
- 系統學習 TypeScript(五)——聯合型別TypeScript型別
- 系統學習 TypeScript(三)——基礎型別TypeScript型別
- C#學習 [型別系統] 類(13)C#型別
- C#學習 [型別系統] 介面(15)C#型別
- C#學習 [型別系統] 型別轉換(11)C#型別
- Java泛型知識點:泛型類、泛型介面和泛型方法Java泛型
- 泛型類、泛型方法及泛型應用泛型
- Python學習之旅(二十一)Python
- C#學習 [型別系統] 基本型別介紹(10)C#型別