檀香楠木 發表於 2022-8-24 08:37:15

Swift泛型Generics浅析讲解

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>泛型(Generics)</li><li>汇编分析泛型的实现原理</li><li>关联类型(Associated Type)</li><li>类型约束</li><li>协议类型的注意点</li><li>泛型解决</li><li>不透明类型(Opaque Type)</li></ul></div><p class="maodian"></p><h2>泛型(Generics)</h2>
<p>1、泛型可以将类型参数化,提高代码复用率,减少代码量</p>
<div class="jb51code"><pre class="brush:java;">func swapValue&lt;T&gt;(_ a: inout T, _ b: inout T) -&gt; Void {
    (a, b) = (b, a)
}</pre></div>
<div class="jb51code"><pre class="brush:java;">var fn: (inout Int, inout Int) -&gt; () = swapValue</pre></div>
<p>栈</p>
<div class="jb51code"><pre class="brush:java;">class Stack&lt;E&gt; {
    var elements = ()
    func push(_ element: E) -&gt; Void {
      elements.append(element)
    }
    func pop() -&gt; E {
      elements.removeLast()
    }
    func top() -&gt; E {
      elements.last!
    }
    func size() -&gt; Int {
      elements.count
    }
}
var intStack = Stack&lt;Int&gt;()
var stringStack = Stack&lt;String&gt;()
var anyStack = Stack&lt;Any&gt;()</pre></div>
<div class="jb51code"><pre class="brush:java;">class SubStack&lt;E&gt;: Stack&lt;E&gt; {
}
struct Stack&lt;E&gt; {
    var elements = ()
    mutating func push(_ element: E) {
      elements.append(element)
    }
    mutating func pop() -&gt; E {
      elements.removeLast()
    }
    func top() -&gt; E {
      elements.last!
    }
    func size() -&gt; Int {
      elements.count
    }
}</pre></div>
<p class="maodian"></p><h2>汇编分析泛型的实现原理</h2>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202208/202208240837542.png" /></p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202208/202208240837543.png" /></p>
<p>通过汇编我们可以看到两次调用的swapValues方法的地址是相同的,也就是说是相同的方法,汇编中有关于metadata的信息,所以推测Swift中的泛型是通过对元数据的处理实现的。</p>
<p class="maodian"></p><h2>关联类型(Associated Type)</h2>
<p>1、关联类型的作用:给协议中用到的类型定义一个占位名称</p>
<p>2、协议中可以拥有多个关联类型</p>
<div class="jb51code"><pre class="brush:java;">protocol Stackable {
    associatedtype Element
    mutating func push(_ element: Element)
    mutating func pop() -&gt; Element
    func top() -&gt; Element
    func size() -&gt; Int
}</pre></div>
<div class="jb51code"><pre class="brush:java;">class StringStack: Stackable {
//    typealias Element = String 可写可不写
    var elements = ()
    func push(_ element: String) -&gt; Void {
      elements.append(element)
    }
    func pop() -&gt; String {
      elements.removeLast()
    }
    func top() -&gt; String {
      elements.last!
    }
    func size() -&gt; Int {
      elements.count
    }
}</pre></div>
<p class="maodian"></p><h2>类型约束</h2>
<div class="jb51code"><pre class="brush:java;">protocol Runnable {}
class Person {}
func swapValues&lt;T: Person &amp; Runnable&gt;(_ a: inout T, _ b: inout T) -&gt; Void {
    (a, b) = (b, a)
}</pre></div>
<p>更多的约束</p>
<div class="jb51code"><pre class="brush:java;">func equal&lt;S1: Stackable, S2: Stackable&gt;(_ s1: S1, _ s2: S2) -&gt; Bool
where S1.Element == S2.Element, S1.Element: Hashable
{
    return false
}</pre></div>
<p class="maodian"></p><h2>协议类型的注意点</h2>
<div class="jb51code"><pre class="brush:java;">protocol Runnable {}
class Person: Runnable {}
class Car: Runnable {}
func getObject(_ type: Int) -&gt; Runnable {
    if type == 0 {
      return Person()
    }
    return Car()
}
var r1 = getObject(0)
var r2 = getObject(1)</pre></div>
<p>1、如果协议中有associatedtype,那么会有类型识别不了的问题,以下代码会报错</p>
<div class="jb51code"><pre class="brush:java;">protocol Runnable {
    associatedtype Speed
    var speed: Speed {
      get
    }
}
class Person: Runnable {
    var speed: Double {
      0.0
    }
}
class Car: Runnable {
    var speed: Int {
      0
    }
}
func getObject(_ type: Int) -&gt; Runnable {
    if type == 0 {
      return Person()
    }
    return Car()
}</pre></div>
<p class="maodian"></p><h2>泛型解决</h2>
<p>解决方案1:使用泛型</p>
<div class="jb51code"><pre class="brush:java;">protocol Runnable {
    associatedtype Speed
    var speed: Speed {
      get
    }
}
class Person: Runnable {
    var speed: Double {
      0.0
    }
}
class Car: Runnable {
    var speed: Int {
      0
    }
}
func getObject&lt;T: Runnable&gt;(_ type: Int) -&gt; T {
    if type == 0 {
      return Person() as! T
    }
    return Car() as! T
}
var r1: Person = getObject(0)
var r2: Car = getObject(1)</pre></div>
<p class="maodian"></p><h2>不透明类型(Opaque Type)</h2>
<p>1、解决方案2:使用some关键字声明一个不透明类型</p>
<div class="jb51code"><pre class="brush:java;">func getObject(_ type: Int) -&gt; some Runnable {
    return Car()
}</pre></div>
<p>2、some限制只能返回一种类型</p>
<p>some</p>
<p>1、some除了用在返回值类型上,一般还可以用在属性类型上</p>
<div class="jb51code"><pre class="brush:java;">protocol Runnable {
    associatedtype Speed
}
class Dog: Runnable {
    typealias Speed = Double
}
class Person {
    var pet: some Runnable {
      return Dog()
    }
}</pre></div>
<p>到此这篇关于Swift泛型Generics浅析讲解的文章就介绍到这了,更多相关Swift&nbsp;Generics内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>解析Swift中的泛型支持与使用</li><li>Swift编程中的泛型解析</li><li>初步理解Swift中的泛型</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: Swift泛型Generics浅析讲解