123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409 |
- <!DOCTYPE html>
- <html lang="en-US">
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width,initial-scale=1">
- <title>Rust入门教程(六):泛型和特性 | Rust训练营教程文档</title>
- <meta name="generator" content="VuePress 1.9.10">
- <link rel="icon" href="/rust_camp_tutorial/logo.png">
- <meta name="description" content="DragonOS-Rust camp">
-
- <link rel="preload" href="/rust_camp_tutorial/assets/css/0.styles.7dd9be3e.css" as="style"><link rel="preload" href="/rust_camp_tutorial/assets/js/app.d7ab8f65.js" as="script"><link rel="preload" href="/rust_camp_tutorial/assets/js/2.3dc1b8de.js" as="script"><link rel="preload" href="/rust_camp_tutorial/assets/js/1.7f771cfb.js" as="script"><link rel="preload" href="/rust_camp_tutorial/assets/js/31.e1aa8cbc.js" as="script"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/10.23a1f579.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/11.c389195a.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/12.1d996921.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/13.4d4410c4.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/14.37ef2a72.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/15.5542c093.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/16.d48fd1ce.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/17.bd8d538c.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/18.6d3b94c1.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/19.eb35cfee.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/20.c11ec329.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/21.db1b5d88.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/22.7714be7b.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/23.7f3a9620.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/24.2f88b37d.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/25.df99dd5f.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/26.606cfbc8.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/27.928f1e6b.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/28.f61a69ee.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/29.802642cf.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/3.5322f14a.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/30.72f41aed.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/32.30c1ff3b.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/33.f21667a4.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/4.84e1e480.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/5.f0541060.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/6.dfb06aa0.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/7.7551a9fb.js"><link rel="prefetch" href="/rust_camp_tutorial/assets/js/vendors~docsearch.5e19b665.js">
- <link rel="stylesheet" href="/rust_camp_tutorial/assets/css/0.styles.7dd9be3e.css">
- </head>
- <body>
- <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/rust_camp_tutorial/" class="home-link router-link-active"><img src="logo.png" alt="Rust训练营教程文档" class="logo"> <span class="site-name can-hide">Rust训练营教程文档</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/rust_camp_tutorial/" class="nav-link">
- 首页
- </a></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/rust_camp_tutorial/" class="nav-link">
- 首页
- </a></div> <!----></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>Rust入门教程(六):泛型和特性</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/rust_camp_tutorial/Rust%E6%96%87%E6%A1%A3/Rust%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%EF%BC%88%E5%85%AD%EF%BC%89.html#_1-泛型" class="sidebar-link">1. 泛型</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/rust_camp_tutorial/Rust%E6%96%87%E6%A1%A3/Rust%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%EF%BC%88%E5%85%AD%EF%BC%89.html#_1-1-泛型介绍" class="sidebar-link">1.1 泛型介绍</a></li><li class="sidebar-sub-header"><a href="/rust_camp_tutorial/Rust%E6%96%87%E6%A1%A3/Rust%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%EF%BC%88%E5%85%AD%EF%BC%89.html#_1-2-在函数定义中使用泛型" class="sidebar-link">1.2 在函数定义中使用泛型</a></li><li class="sidebar-sub-header"><a href="/rust_camp_tutorial/Rust%E6%96%87%E6%A1%A3/Rust%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%EF%BC%88%E5%85%AD%EF%BC%89.html#_1-3-结构体中的泛型" class="sidebar-link">1.3 结构体中的泛型</a></li><li class="sidebar-sub-header"><a href="/rust_camp_tutorial/Rust%E6%96%87%E6%A1%A3/Rust%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%EF%BC%88%E5%85%AD%EF%BC%89.html#_1-4-enum定义中的泛型" class="sidebar-link">1.4 Enum定义中的泛型</a></li><li class="sidebar-sub-header"><a href="/rust_camp_tutorial/Rust%E6%96%87%E6%A1%A3/Rust%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%EF%BC%88%E5%85%AD%EF%BC%89.html#_1-5-方法定义中使用泛型" class="sidebar-link">1.5 方法定义中使用泛型</a></li><li class="sidebar-sub-header"><a href="/rust_camp_tutorial/Rust%E6%96%87%E6%A1%A3/Rust%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%EF%BC%88%E5%85%AD%EF%BC%89.html#_1-6-泛型代码的性能" class="sidebar-link">1.6 泛型代码的性能</a></li></ul></li><li><a href="/rust_camp_tutorial/Rust%E6%96%87%E6%A1%A3/Rust%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%EF%BC%88%E5%85%AD%EF%BC%89.html#_2-trait" class="sidebar-link">2. trait</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/rust_camp_tutorial/Rust%E6%96%87%E6%A1%A3/Rust%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%EF%BC%88%E5%85%AD%EF%BC%89.html#_2-1-定义一个-trait" class="sidebar-link">2.1 定义一个 Trait</a></li><li class="sidebar-sub-header"><a href="/rust_camp_tutorial/Rust%E6%96%87%E6%A1%A3/Rust%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%EF%BC%88%E5%85%AD%EF%BC%89.html#_2-2-在类型上实现-trait" class="sidebar-link">2.2 在类型上实现 trait</a></li><li class="sidebar-sub-header"><a href="/rust_camp_tutorial/Rust%E6%96%87%E6%A1%A3/Rust%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%EF%BC%88%E5%85%AD%EF%BC%89.html#_2-3-实现-trait-的约束" class="sidebar-link">2.3 实现 trait 的约束</a></li><li class="sidebar-sub-header"><a href="/rust_camp_tutorial/Rust%E6%96%87%E6%A1%A3/Rust%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%EF%BC%88%E5%85%AD%EF%BC%89.html#附" class="sidebar-link">附</a></li><li class="sidebar-sub-header"><a href="/rust_camp_tutorial/Rust%E6%96%87%E6%A1%A3/Rust%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%EF%BC%88%E5%85%AD%EF%BC%89.html#_2-4-实现-trait-作为参数" class="sidebar-link">2.4 实现 Trait 作为参数</a></li><li class="sidebar-sub-header"><a href="/rust_camp_tutorial/Rust%E6%96%87%E6%A1%A3/Rust%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%EF%BC%88%E5%85%AD%EF%BC%89.html#_2-5-实现-trait-作为返回类型" class="sidebar-link">2.5 实现 Trait 作为返回类型</a></li><li class="sidebar-sub-header"><a href="/rust_camp_tutorial/Rust%E6%96%87%E6%A1%A3/Rust%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%EF%BC%88%E5%85%AD%EF%BC%89.html#_2-6-使用-trait-bound-实现之前泛型-的例子" class="sidebar-link">2.6 使用 trait bound 实现之前泛型 的例子</a></li><li class="sidebar-sub-header"><a href="/rust_camp_tutorial/Rust%E6%96%87%E6%A1%A3/Rust%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B%EF%BC%88%E5%85%AD%EF%BC%89.html#_2-7-使用-trait-bound-有条件的实现方法" class="sidebar-link">2.7 使用 Trait Bound 有条件的实现方法</a></li></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="rust入门教程-六-泛型和特性"><a href="#rust入门教程-六-泛型和特性" class="header-anchor">#</a> Rust入门教程(六):泛型和特性</h1> <blockquote><p>泛型是一个编程语言不可或缺的机制。
- C++ 语言中用"模板"来实现泛型,而 C 语言中没有泛型的机制,这也导致 C 语言难以构建类型复杂的工程。
- 泛型机制是编程语言用于表达类型抽象的机制,一般用于功能确定、数据类型待定的类,如链表、映射表等。</p></blockquote> <h2 id="_1-泛型"><a href="#_1-泛型" class="header-anchor">#</a> 1. 泛型</h2> <h3 id="_1-1-泛型介绍"><a href="#_1-1-泛型介绍" class="header-anchor">#</a> 1.1 泛型介绍</h3> <ul><li>泛型可以提高代码复用能力,也就是处理重复代码的问题</li> <li>泛型是具体类型或其它属性的抽象代替:
- <ul><li>你编写的代码不是最终的代码,而是一种模板,里面有一些“占位符”</li> <li>编译器在编译时将<strong>占位符</strong>替换为具体的类型</li> <li>例如:<code>fn largest<T>(list: &[T]) ->T {...}</code></li></ul></li> <li>类型参数
- <ul><li>很短,通常一个字母</li> <li>CamelCase</li> <li>T: type 的缩写</li></ul></li></ul> <h3 id="_1-2-在函数定义中使用泛型"><a href="#_1-2-在函数定义中使用泛型" class="header-anchor">#</a> 1.2 在函数定义中使用泛型</h3> <p>泛型函数</p> <ul><li>参数类型</li> <li>返回类型</li></ul> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">fn</span> <span class="token function-definition function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
- <span class="token keyword">let</span> a <span class="token operator">=</span> <span class="token macro property">vec!</span><span class="token punctuation">[</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">80</span><span class="token punctuation">,</span> <span class="token number">2022</span><span class="token punctuation">,</span> <span class="token number">36</span><span class="token punctuation">,</span> <span class="token number">47</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
- <span class="token keyword">let</span> largest <span class="token operator">=</span> <span class="token function">largest</span><span class="token punctuation">(</span><span class="token operator">&</span>a<span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"The largest ele is {}"</span><span class="token punctuation">,</span> largest<span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">largest</span><span class="token punctuation">(</span>list<span class="token punctuation">:</span> <span class="token operator">&</span><span class="token punctuation">[</span><span class="token keyword">i32</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token keyword">i32</span> <span class="token punctuation">{</span>
- <span class="token keyword">let</span> <span class="token keyword">mut</span> largest <span class="token operator">=</span> list<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
- <span class="token keyword">for</span> <span class="token operator">&</span>item <span class="token keyword">in</span> list <span class="token punctuation">{</span>
- <span class="token keyword">if</span> item <span class="token operator">></span> largest <span class="token punctuation">{</span>
- largest <span class="token operator">=</span> item<span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- <span class="token punctuation">}</span>
- largest
- <span class="token punctuation">}</span>
- </code></pre></div><p>上面这段代码是求一个集合中最大的元素,我们定义的集合是一个 <code>i32</code> 类型,但是这时如果我们要传入 <code>f32</code> 或者字符型,还用同样的逻辑判断函数的话,是会报错的,这时我们就需要用到泛型。</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">fn</span> <span class="token function-definition function">largest</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token operator">></span><span class="token punctuation">(</span>list<span class="token punctuation">:</span> <span class="token operator">&</span><span class="token punctuation">[</span><span class="token class-name">T</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">T</span> <span class="token punctuation">{</span>
- <span class="token keyword">let</span> <span class="token keyword">mut</span> largest <span class="token operator">=</span> list<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
- <span class="token keyword">for</span> <span class="token operator">&</span>item <span class="token keyword">in</span> list <span class="token punctuation">{</span>
- <span class="token keyword">if</span> item <span class="token operator">></span> largest <span class="token punctuation">{</span>
- largest <span class="token operator">=</span> item<span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- <span class="token punctuation">}</span>
- largest
- <span class="token punctuation">}</span>
- </code></pre></div><p>我们声明了一个泛型 <code>T</code>,但是这样是会编译报错的,因为不是所有类型 T 都可以进行大小比较,只有实现了下面的 <code>std::cmp::PartialOrd</code> 的 trait 才能进行大小比较,所以要对 T 进行约束。</p> <div class="language-rust extra-class"><pre class="language-rust"><code>➜ ~<span class="token operator">/</span><span class="token class-name">Code</span><span class="token operator">/</span>rust<span class="token operator">/</span>pattern git<span class="token punctuation">:</span><span class="token punctuation">(</span>master<span class="token punctuation">)</span> ✗ cargo run
- <span class="token class-name">Compiling</span> pattern v0<span class="token number">.1</span><span class="token punctuation">.</span><span class="token number">0</span> <span class="token punctuation">(</span><span class="token operator">/</span>home<span class="token operator">/</span>cherry<span class="token operator">/</span><span class="token class-name">Code</span><span class="token operator">/</span>rust<span class="token operator">/</span>pattern<span class="token punctuation">)</span>
- error<span class="token punctuation">[</span><span class="token constant">E0369</span><span class="token punctuation">]</span><span class="token punctuation">:</span> binary operation `<span class="token operator">></span>` cannot be applied to <span class="token keyword">type</span> `<span class="token class-name">T</span>`
- <span class="token operator">-</span><span class="token punctuation">-></span> src<span class="token operator">/</span>main<span class="token punctuation">.</span>rs<span class="token punctuation">:</span><span class="token number">10</span><span class="token punctuation">:</span><span class="token number">17</span>
- <span class="token operator">|</span>
- <span class="token number">10</span> <span class="token operator">|</span> <span class="token keyword">if</span> item <span class="token operator">></span> largest <span class="token punctuation">{</span>
- <span class="token operator">|</span> <span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span> <span class="token operator">^</span> <span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span> <span class="token class-name">T</span>
- <span class="token operator">|</span> <span class="token operator">|</span>
- <span class="token operator">|</span> <span class="token class-name">T</span>
- <span class="token operator">|</span>
- help<span class="token punctuation">:</span> consider restricting <span class="token keyword">type</span> <span class="token type-definition class-name">parameter</span> `<span class="token class-name">T</span>`
- <span class="token operator">|</span>
- <span class="token number">7</span> <span class="token operator">|</span> <span class="token keyword">fn</span> <span class="token function-definition function">largest</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token punctuation">:</span> <span class="token namespace">std<span class="token punctuation">::</span>cmp<span class="token punctuation">::</span></span><span class="token class-name">PartialOrd</span><span class="token operator">></span><span class="token punctuation">(</span>list<span class="token punctuation">:</span> <span class="token operator">&</span><span class="token punctuation">[</span><span class="token class-name">T</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">T</span> <span class="token punctuation">{</span>
- <span class="token operator">|</span> <span class="token operator">+</span><span class="token operator">+</span><span class="token operator">+</span><span class="token operator">+</span><span class="token operator">+</span><span class="token operator">+</span><span class="token operator">+</span><span class="token operator">+</span><span class="token operator">+</span><span class="token operator">+</span><span class="token operator">+</span><span class="token operator">+</span><span class="token operator">+</span><span class="token operator">+</span><span class="token operator">+</span><span class="token operator">+</span><span class="token operator">+</span><span class="token operator">+</span><span class="token operator">+</span><span class="token operator">+</span><span class="token operator">+</span><span class="token operator">+</span>
- <span class="token class-name">For</span> more information about this error<span class="token punctuation">,</span> <span class="token keyword">try</span> `rustc <span class="token operator">-</span><span class="token operator">-</span>explain <span class="token constant">E0369</span>`<span class="token punctuation">.</span>
- error<span class="token punctuation">:</span> could not compile `pattern` due to previous error
- </code></pre></div><p>但是把 <code>std::cmp::PartialOrd</code> 这个 trait 加上又会报其他错误,这里在后面会进行介绍。</p> <h3 id="_1-3-结构体中的泛型"><a href="#_1-3-结构体中的泛型" class="header-anchor">#</a> 1.3 结构体中的泛型</h3> <p>可以使用多个泛型的类型参数,但是也不要有太多的类型,否则代码可读性将会下降。例如:</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">struct</span> <span class="token type-definition class-name">Point</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token punctuation">,</span> <span class="token class-name">U</span><span class="token operator">></span> <span class="token punctuation">{</span>
- x<span class="token punctuation">:</span> <span class="token class-name">T</span><span class="token punctuation">,</span>
- y<span class="token punctuation">:</span> <span class="token class-name">U</span><span class="token punctuation">,</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">test01</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
- <span class="token keyword">let</span> integer <span class="token operator">=</span> <span class="token class-name">Point</span><span class="token punctuation">{</span>x<span class="token punctuation">:</span> <span class="token number">2022</span><span class="token punctuation">,</span> y<span class="token punctuation">:</span> <span class="token number">6.1</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- </code></pre></div><h3 id="_1-4-enum定义中的泛型"><a href="#_1-4-enum定义中的泛型" class="header-anchor">#</a> 1.4 Enum定义中的泛型</h3> <p>可以让枚举的变体持有泛型数据类型,例如:Option<T>, Result<T, E></T></p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">enum</span> <span class="token type-definition class-name">Option</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token operator">></span> <span class="token punctuation">{</span>
- <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token class-name">T</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
- <span class="token class-name">None</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">enum</span> <span class="token type-definition class-name">Result</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token punctuation">,</span> <span class="token class-name">E</span><span class="token operator">></span> <span class="token punctuation">{</span>
- <span class="token class-name">Ok</span><span class="token punctuation">(</span><span class="token class-name">T</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
- <span class="token class-name">Err</span><span class="token punctuation">(</span><span class="token class-name">E</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
- <span class="token punctuation">}</span>
- </code></pre></div><h3 id="_1-5-方法定义中使用泛型"><a href="#_1-5-方法定义中使用泛型" class="header-anchor">#</a> 1.5 方法定义中使用泛型</h3> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">fn</span> <span class="token function-definition function">test01</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
- <span class="token keyword">let</span> integer <span class="token operator">=</span> <span class="token class-name">Point</span><span class="token punctuation">{</span>x<span class="token punctuation">:</span> <span class="token number">2022</span><span class="token punctuation">,</span> y<span class="token punctuation">:</span> <span class="token number">61</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
- <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"{}"</span><span class="token punctuation">,</span> integer<span class="token punctuation">.</span><span class="token function">x</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">impl</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token operator">></span> <span class="token class-name">Point</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token operator">></span> <span class="token punctuation">{</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">x</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token operator">&</span><span class="token class-name">T</span> <span class="token punctuation">{</span>
- <span class="token operator">&</span><span class="token keyword">self</span><span class="token punctuation">.</span>x
- <span class="token punctuation">}</span>
- <span class="token punctuation">}</span>
- </code></pre></div><p>注意</p> <ul><li>把 T 放在 impl 关键字后,表示在类型 T 上实现方法
- <ul><li>例如:<code>impl<T> Point<T></code></li></ul></li> <li>只针对具体类型实现方法(其余类型没实现方法)
- <ul><li>例如: <code>impl Point<f32></code></li></ul></li> <li>struct 中的泛型参数可以和方法的泛型参数不同</li></ul> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">impl</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token punctuation">,</span> <span class="token class-name">U</span><span class="token operator">></span> <span class="token class-name">Point</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token punctuation">,</span> <span class="token class-name">U</span><span class="token operator">></span> <span class="token punctuation">{</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">x</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token operator">&</span><span class="token class-name">T</span> <span class="token punctuation">{</span>
- <span class="token operator">&</span><span class="token keyword">self</span><span class="token punctuation">.</span>x
- <span class="token punctuation">}</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">impl</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token punctuation">,</span> <span class="token class-name">U</span><span class="token operator">></span> <span class="token class-name">Point</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token punctuation">,</span> <span class="token class-name">U</span><span class="token operator">></span> <span class="token punctuation">{</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">mixup</span><span class="token operator"><</span><span class="token class-name">V</span><span class="token punctuation">,</span> <span class="token class-name">W</span><span class="token operator">></span><span class="token punctuation">(</span><span class="token keyword">self</span><span class="token punctuation">,</span> other<span class="token punctuation">:</span> <span class="token class-name">Point</span><span class="token operator"><</span><span class="token class-name">V</span><span class="token punctuation">,</span><span class="token class-name">W</span><span class="token operator">></span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">Point</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token punctuation">,</span> <span class="token class-name">W</span><span class="token operator">></span> <span class="token punctuation">{</span>
- <span class="token class-name">Point</span> <span class="token punctuation">{</span>
- x<span class="token punctuation">:</span> <span class="token keyword">self</span><span class="token punctuation">.</span>x<span class="token punctuation">,</span>
- y<span class="token punctuation">:</span> other<span class="token punctuation">.</span>y
- <span class="token punctuation">}</span>
- <span class="token punctuation">}</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">test02</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
- <span class="token keyword">let</span> p1 <span class="token operator">=</span> <span class="token class-name">Point</span><span class="token punctuation">{</span>x<span class="token punctuation">:</span> <span class="token number">61</span><span class="token punctuation">,</span> y<span class="token punctuation">:</span> <span class="token number">85</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
- <span class="token keyword">let</span> p2 <span class="token operator">=</span> <span class="token class-name">Point</span><span class="token punctuation">{</span>x<span class="token punctuation">:</span> <span class="token string">"Hello"</span><span class="token punctuation">,</span> y<span class="token punctuation">:</span> <span class="token string">"Rust"</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
- <span class="token keyword">let</span> p3 <span class="token operator">=</span> p1<span class="token punctuation">.</span><span class="token function">mixup</span><span class="token punctuation">(</span>p2<span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"p3.x = {}, p3.y = {}"</span><span class="token punctuation">,</span> p3<span class="token punctuation">.</span>x<span class="token punctuation">,</span> p3<span class="token punctuation">.</span>y<span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- </code></pre></div><p>上面实现的结构体方法实际上是将第一个 Point 中的 x 和第二个 Point 的 y 结合起来形成一个新的 Point。</p> <h3 id="_1-6-泛型代码的性能"><a href="#_1-6-泛型代码的性能" class="header-anchor">#</a> 1.6 泛型代码的性能</h3> <p>使用泛型的代码和使用具体类型的代码运行速度是一样的</p> <ul><li>单态化(monomorphization)
- <ul><li>在编译时将泛型替换为具体类型的过程</li></ul></li></ul> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">let</span> ingeter <span class="token operator">=</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token keyword">let</span> float <span class="token operator">=</span> <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token number">5.0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token keyword">enum</span> <span class="token type-definition class-name">Option_i32</span> <span class="token punctuation">{</span>
- <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token keyword">i32</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
- <span class="token class-name">None</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">enum</span> <span class="token type-definition class-name">Option_f32</span> <span class="token punctuation">{</span>
- <span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token keyword">f32</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
- <span class="token class-name">None</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
- <span class="token keyword">let</span> integer <span class="token operator">=</span> <span class="token class-name">Option_i32</span><span class="token punctuation">::</span><span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token keyword">let</span> float <span class="token operator">=</span> <span class="token class-name">Option_f64</span><span class="token punctuation">::</span><span class="token class-name">Some</span><span class="token punctuation">(</span><span class="token number">5.0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- </code></pre></div><h2 id="_2-trait"><a href="#_2-trait" class="header-anchor">#</a> 2. trait</h2> <ul><li>Trait 告诉 Rust 编译器
- <ul><li>某种类型具有哪些并且可以与其它类型共享的功能</li></ul></li> <li>Trait:抽象的定义共享行为</li> <li>Trait bounds(约束):泛型类型参数指定为实现了特定行为的类型</li> <li>Trait与其它语言的接口(interface)类似,但有些区别</li></ul> <h3 id="_2-1-定义一个-trait"><a href="#_2-1-定义一个-trait" class="header-anchor">#</a> 2.1 定义一个 Trait</h3> <p>Trait的定义:把方法签名放在一起,来定义实现某种目的所必需的一组行为。</p> <ul><li>关键字:trait</li> <li>只有方法签名,没有具体实现</li> <li>trait 可以有多个方法:每个方法签名占一行,以 <code>;</code> 结尾</li> <li>实现该 trait 的类型必须提供具体的方法实现</li></ul> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">pub</span> <span class="token keyword">trait</span> <span class="token type-definition class-name">Summary</span> <span class="token punctuation">{</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">summarize</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- </code></pre></div><h3 id="_2-2-在类型上实现-trait"><a href="#_2-2-在类型上实现-trait" class="header-anchor">#</a> 2.2 在类型上实现 trait</h3> <ul><li>在类型上实现 trait。与为类型实现方法类似</li> <li>不同之处:<code>impl Xxxx for Tweet {...}</code></li> <li>在 impl 的块里,需要对 Trait 里的方法签名进行具体的实现</li></ul> <p>文件 <code>lib.rs</code>:</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">pub</span> <span class="token keyword">trait</span> <span class="token type-definition class-name">Summary</span> <span class="token punctuation">{</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">summarize</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">NewsArticle</span> <span class="token punctuation">{</span>
- <span class="token keyword">pub</span> headline<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">,</span>
- <span class="token keyword">pub</span> location<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">,</span>
- <span class="token keyword">pub</span> author<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">,</span>
- <span class="token keyword">pub</span> content<span class="token punctuation">:</span> <span class="token class-name">String</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">impl</span> <span class="token class-name">Summary</span> <span class="token keyword">for</span> <span class="token class-name">NewsArticle</span> <span class="token punctuation">{</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">summarize</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span> <span class="token punctuation">{</span>
- <span class="token macro property">format!</span><span class="token punctuation">(</span><span class="token string">"{}, by {} ({})"</span><span class="token punctuation">,</span> <span class="token keyword">self</span><span class="token punctuation">.</span>headline<span class="token punctuation">,</span> <span class="token keyword">self</span><span class="token punctuation">.</span>author<span class="token punctuation">,</span> <span class="token keyword">self</span><span class="token punctuation">.</span>location<span class="token punctuation">)</span>
- <span class="token punctuation">}</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">Tweet</span> <span class="token punctuation">{</span>
- <span class="token keyword">pub</span> username<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">,</span>
- <span class="token keyword">pub</span> content<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">,</span>
- <span class="token keyword">pub</span> reply<span class="token punctuation">:</span> <span class="token keyword">bool</span><span class="token punctuation">,</span>
- <span class="token keyword">pub</span> retweet<span class="token punctuation">:</span> <span class="token keyword">bool</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">impl</span> <span class="token class-name">Summary</span> <span class="token keyword">for</span> <span class="token class-name">Tweet</span> <span class="token punctuation">{</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">summarize</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span> <span class="token punctuation">{</span>
- <span class="token macro property">format!</span><span class="token punctuation">(</span><span class="token string">"{}: {}"</span><span class="token punctuation">,</span> <span class="token keyword">self</span><span class="token punctuation">.</span>username<span class="token punctuation">,</span> <span class="token keyword">self</span><span class="token punctuation">.</span>content<span class="token punctuation">)</span>
- <span class="token punctuation">}</span>
- <span class="token punctuation">}</span>
- </code></pre></div><p>文件 <code>main.rs</code>:</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">use</span> <span class="token namespace">trait_demo<span class="token punctuation">::</span></span><span class="token class-name">Summary</span><span class="token punctuation">;</span>
- <span class="token keyword">use</span> <span class="token namespace">trait_demo<span class="token punctuation">::</span></span><span class="token class-name">Tweet</span><span class="token punctuation">;</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
- <span class="token keyword">let</span> tweet <span class="token operator">=</span> <span class="token class-name">Tweet</span> <span class="token punctuation">{</span>
- username<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"Cherry_ICT"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
- content<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"People in Shanghai are free today..."</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
- reply<span class="token punctuation">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
- retweet<span class="token punctuation">:</span> <span class="token boolean">false</span>
- <span class="token punctuation">}</span><span class="token punctuation">;</span>
- <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"Get 1 new tweet: {}"</span><span class="token punctuation">,</span> tweet<span class="token punctuation">.</span><span class="token function">summarize</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- </code></pre></div><p>实现的功能很简单,不做具体解释了。</p> <h3 id="_2-3-实现-trait-的约束"><a href="#_2-3-实现-trait-的约束" class="header-anchor">#</a> 2.3 实现 trait 的约束</h3> <ul><li>可以在某个类型上实现某个 trait 的前提条件是
- <ul><li>这个类型或这个 trait 是在本地 crate 里定义的</li></ul></li> <li>无法为外部类型来实现外部的trait
- <ul><li>这个限制是程序属性的一部分(也就是一致性)</li> <li>更具体地说是<strong>孤儿规则</strong>:之所以这样命名是因为父类型不存在</li> <li>此规则确保其他人的代码不能破坏您的代码,反之亦然</li> <li>如果没有这个规则,两个 crate 可以为同一类型实现同一个 trait,Rust 就不知道应该使用哪个实现了</li></ul></li></ul> <p><strong>默认实现</strong></p> <p>默认实现的方法可以调用 trait 中的其他方法,即使这些方法没有默认实现,但是注意,无法从方法的重写实现中调用默认实现。</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">pub</span> <span class="token keyword">trait</span> <span class="token type-definition class-name">Summary</span> <span class="token punctuation">{</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">summarize</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span> <span class="token punctuation">{</span>
- <span class="token macro property">format!</span><span class="token punctuation">(</span><span class="token string">"(Read more from {} ...)"</span><span class="token punctuation">,</span> <span class="token keyword">self</span><span class="token punctuation">.</span><span class="token function">summarize_author</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">summarize_author</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- </code></pre></div><p>在 trait 中可以有方法的默认实现,在默认实现的基础上,类型可以对该 trait 进行重载。同样,在 trait 中默认实现的方法可以实现 trait 中其他方法。</p> <h3 id="附"><a href="#附" class="header-anchor">#</a> 附</h3> <p>刚刚 trait 例子的完整代码如下:</p> <p><code>lib.rs</code>:</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">pub</span> <span class="token keyword">trait</span> <span class="token type-definition class-name">Summary</span> <span class="token punctuation">{</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">summarize</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span> <span class="token punctuation">{</span>
- <span class="token macro property">format!</span><span class="token punctuation">(</span><span class="token string">"(Read more from {} ...)"</span><span class="token punctuation">,</span> <span class="token keyword">self</span><span class="token punctuation">.</span><span class="token function">summarize_author</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">summarize_author</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">NewsArticle</span> <span class="token punctuation">{</span>
- <span class="token keyword">pub</span> headline<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">,</span>
- <span class="token keyword">pub</span> location<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">,</span>
- <span class="token keyword">pub</span> author<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">,</span>
- <span class="token keyword">pub</span> content<span class="token punctuation">:</span> <span class="token class-name">String</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">impl</span> <span class="token class-name">Summary</span> <span class="token keyword">for</span> <span class="token class-name">NewsArticle</span> <span class="token punctuation">{</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">summarize</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span> <span class="token punctuation">{</span>
- <span class="token macro property">format!</span><span class="token punctuation">(</span><span class="token string">"{}, by {} ({})"</span><span class="token punctuation">,</span> <span class="token keyword">self</span><span class="token punctuation">.</span>headline<span class="token punctuation">,</span> <span class="token keyword">self</span><span class="token punctuation">.</span>author<span class="token punctuation">,</span> <span class="token keyword">self</span><span class="token punctuation">.</span>location<span class="token punctuation">)</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">summarize_author</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span> <span class="token punctuation">{</span>
- <span class="token macro property">format!</span><span class="token punctuation">(</span><span class="token string">"@{}"</span><span class="token punctuation">,</span> <span class="token keyword">self</span><span class="token punctuation">.</span>author<span class="token punctuation">)</span>
- <span class="token punctuation">}</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">Tweet</span> <span class="token punctuation">{</span>
- <span class="token keyword">pub</span> username<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">,</span>
- <span class="token keyword">pub</span> content<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">,</span>
- <span class="token keyword">pub</span> reply<span class="token punctuation">:</span> <span class="token keyword">bool</span><span class="token punctuation">,</span>
- <span class="token keyword">pub</span> retweet<span class="token punctuation">:</span> <span class="token keyword">bool</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">impl</span> <span class="token class-name">Summary</span> <span class="token keyword">for</span> <span class="token class-name">Tweet</span> <span class="token punctuation">{</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">summarize</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span> <span class="token punctuation">{</span>
- <span class="token macro property">format!</span><span class="token punctuation">(</span><span class="token string">"{}: {}"</span><span class="token punctuation">,</span> <span class="token keyword">self</span><span class="token punctuation">.</span>username<span class="token punctuation">,</span> <span class="token keyword">self</span><span class="token punctuation">.</span>content<span class="token punctuation">)</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">summarize_author</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span> <span class="token punctuation">{</span>
- <span class="token macro property">format!</span><span class="token punctuation">(</span><span class="token string">"@{}"</span><span class="token punctuation">,</span> <span class="token keyword">self</span><span class="token punctuation">.</span>username<span class="token punctuation">)</span>
- <span class="token punctuation">}</span>
- <span class="token punctuation">}</span>
- </code></pre></div><p><code>main.rs</code>:</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">use</span> <span class="token namespace">trait_demo<span class="token punctuation">::</span></span><span class="token class-name">Summary</span><span class="token punctuation">;</span>
- <span class="token keyword">use</span> <span class="token namespace">trait_demo<span class="token punctuation">::</span></span><span class="token class-name">Tweet</span><span class="token punctuation">;</span>
- <span class="token keyword">use</span> <span class="token namespace">trait_demo<span class="token punctuation">::</span></span><span class="token class-name">NewsArticle</span><span class="token punctuation">;</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
- <span class="token keyword">let</span> tweet <span class="token operator">=</span> <span class="token class-name">Tweet</span> <span class="token punctuation">{</span>
- username<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"Cherry_ICT"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
- content<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"People in Shanghai are free today..."</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
- reply<span class="token punctuation">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
- retweet<span class="token punctuation">:</span> <span class="token boolean">false</span>
- <span class="token punctuation">}</span><span class="token punctuation">;</span>
- <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"Get 1 new tweet: {}"</span><span class="token punctuation">,</span> tweet<span class="token punctuation">.</span><span class="token function">summarize</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token keyword">let</span> news <span class="token operator">=</span> <span class="token class-name">NewsArticle</span> <span class="token punctuation">{</span>
- headline<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"WWDC will be held in June 7th"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
- location<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"USA"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
- author<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"Tim Cook"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
- content<span class="token punctuation">:</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"The Apple will take us a lot of devices."</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
- <span class="token punctuation">}</span><span class="token punctuation">;</span>
- <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"You receive a news: {}"</span><span class="token punctuation">,</span> news<span class="token punctuation">.</span><span class="token function">summarize</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- </code></pre></div><p>最终输出结果为:</p> <div class="language-rust extra-class"><pre class="language-rust"><code>➜ ~<span class="token operator">/</span><span class="token class-name">Code</span><span class="token operator">/</span>rust<span class="token operator">/</span>trait_demo git<span class="token punctuation">:</span><span class="token punctuation">(</span>master<span class="token punctuation">)</span> ✗ cargo run
- <span class="token class-name">Compiling</span> trait_demo v0<span class="token number">.1</span><span class="token punctuation">.</span><span class="token number">0</span> <span class="token punctuation">(</span><span class="token operator">/</span>home<span class="token operator">/</span>cherry<span class="token operator">/</span><span class="token class-name">Code</span><span class="token operator">/</span>rust<span class="token operator">/</span>trait_demo<span class="token punctuation">)</span>
- <span class="token class-name">Finished</span> dev <span class="token punctuation">[</span>unoptimized <span class="token operator">+</span> debuginfo<span class="token punctuation">]</span> <span class="token function">target</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token keyword">in</span> <span class="token number">0</span><span class="token punctuation">.</span>33s
- <span class="token class-name">Running</span> `target<span class="token operator">/</span>debug<span class="token operator">/</span>trait_demo`
- <span class="token class-name">Get</span> <span class="token number">1</span> new tweet<span class="token punctuation">:</span> <span class="token class-name">Cherry_ICT</span><span class="token punctuation">:</span> <span class="token class-name">People</span> <span class="token keyword">in</span> <span class="token class-name">Shanghai</span> are free today<span class="token punctuation">...</span>
- <span class="token class-name">You</span> receive a news<span class="token punctuation">:</span> <span class="token constant">WWDC</span> will be held <span class="token keyword">in</span> <span class="token class-name">June</span> 7th<span class="token punctuation">,</span> by <span class="token class-name">Tim</span> <span class="token class-name">Cook</span> <span class="token punctuation">(</span><span class="token constant">USA</span><span class="token punctuation">)</span>
- </code></pre></div><h3 id="_2-4-实现-trait-作为参数"><a href="#_2-4-实现-trait-作为参数" class="header-anchor">#</a> 2.4 实现 Trait 作为参数</h3> <ul><li>impl Trait 语法:适用于简单情况</li> <li>Trait bound 语法:可用于复杂情况
- <ul><li>impl trait 语法实际上是 trait bound 语法的语法糖</li></ul></li> <li>使用 <code>+</code> 指定多个 trait bound</li> <li>Trait bound 使用 where 子句
- <ul><li>在方法签名后指定 where 子句</li></ul></li></ul> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">pub</span> <span class="token keyword">trait</span> <span class="token type-definition class-name">Summary</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
- <span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">NewsArticle</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
- <span class="token keyword">impl</span> <span class="token class-name">Summary</span> <span class="token keyword">for</span> <span class="token class-name">NewsArticle</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
- <span class="token keyword">pub</span> <span class="token keyword">struct</span> <span class="token type-definition class-name">Tweet</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
- <span class="token keyword">impl</span> <span class="token class-name">Summary</span> <span class="token keyword">for</span> <span class="token class-name">Tweet</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
- <span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">notify</span><span class="token punctuation">(</span>item<span class="token punctuation">:</span> <span class="token keyword">impl</span> <span class="token class-name">Summary</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
- <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"Breaking news! {}"</span><span class="token punctuation">,</span> item<span class="token punctuation">.</span><span class="token function">summarize</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- </code></pre></div><p>这是采用 impl Trait 的语法,这里的 notify 方法要求传入的参数可以是 <code>NewsArticle</code> 类型或者是 <code>Tweet</code> 类型,也就是要求参数要实现 <code>Summary</code> 这个 trait,从而使用 summarize 这个方法。</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">notify</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token punctuation">:</span> <span class="token class-name">Summary</span><span class="token operator">></span><span class="token punctuation">(</span>item<span class="token punctuation">:</span> <span class="token class-name">T</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
- <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"Breaking news! {}"</span><span class="token punctuation">,</span> item<span class="token punctuation">.</span><span class="token function">summarize</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- </code></pre></div><p>这是采用 Trait bound 的写法,下面这个例子讲展示出这种写法的优势:</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">notify</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token punctuation">:</span> <span class="token class-name">Summary</span><span class="token operator">></span><span class="token punctuation">(</span>item1<span class="token punctuation">:</span> <span class="token class-name">T</span><span class="token punctuation">,</span> item2<span class="token punctuation">:</span> <span class="token class-name">T</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
- <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"Breaking news! {}"</span><span class="token punctuation">,</span> item<span class="token punctuation">.</span><span class="token function">summarize</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- </code></pre></div><p>当有多个参数时,采用这种写法可以使得代码相对简洁一些。</p> <p>使用 <code>+</code> 指定多个 trait bound:</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">notify1</span><span class="token punctuation">(</span>item<span class="token punctuation">:</span> <span class="token keyword">impl</span> <span class="token class-name">Summary</span> <span class="token operator">+</span> <span class="token class-name">Display</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
- <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"Breaking news! {}"</span><span class="token punctuation">,</span> item<span class="token punctuation">.</span><span class="token function">summarize</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">notify</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token punctuation">:</span> <span class="token class-name">Summary</span> <span class="token operator">+</span> <span class="token class-name">Display</span><span class="token operator">></span><span class="token punctuation">(</span>item<span class="token punctuation">:</span> <span class="token class-name">T</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
- <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"Breaking news! {}"</span><span class="token punctuation">,</span> item<span class="token punctuation">.</span><span class="token function">summarize</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- </code></pre></div><p>然而如果一个函数中参数过多,那么整个函数声明就会变得非常长,不太直观,可读性差,这里可以使用 where 子句来指定 trait 的约束:</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">notify2</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token punctuation">:</span> <span class="token class-name">Summary</span> <span class="token operator">+</span> <span class="token class-name">Display</span><span class="token punctuation">,</span> <span class="token class-name">U</span><span class="token punctuation">:</span> <span class="token class-name">Clone</span> <span class="token operator">+</span> <span class="token class-name">Debug</span><span class="token operator">></span><span class="token punctuation">(</span>a<span class="token punctuation">:</span> <span class="token class-name">T</span><span class="token punctuation">,</span> b<span class="token punctuation">:</span> <span class="token class-name">U</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span> <span class="token punctuation">{</span>
- <span class="token macro property">format!</span><span class="token punctuation">(</span><span class="token string">"Breaking news! {}"</span><span class="token punctuation">,</span> a<span class="token punctuation">.</span><span class="token function">summarize</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
- <span class="token punctuation">}</span>
- </code></pre></div><p>这个例子中函数签名太长,不够直观,采用 where 子句可以使得更加直观:</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">notify3</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token punctuation">,</span> <span class="token class-name">U</span><span class="token operator">></span><span class="token punctuation">(</span>a<span class="token punctuation">:</span> <span class="token class-name">T</span><span class="token punctuation">,</span> b<span class="token punctuation">:</span> <span class="token class-name">U</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">String</span>
- <span class="token keyword">where</span>
- <span class="token class-name">T</span><span class="token punctuation">:</span> <span class="token class-name">Summary</span> <span class="token operator">+</span> <span class="token class-name">Display</span><span class="token punctuation">,</span>
- <span class="token class-name">U</span><span class="token punctuation">:</span> <span class="token class-name">Clone</span> <span class="token operator">+</span> <span class="token class-name">Debug</span><span class="token punctuation">,</span>
- <span class="token punctuation">{</span>
- <span class="token macro property">format!</span><span class="token punctuation">(</span><span class="token string">"Breaking news! {}"</span><span class="token punctuation">,</span> a<span class="token punctuation">.</span><span class="token function">summarize</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
- <span class="token punctuation">}</span>
- </code></pre></div><h3 id="_2-5-实现-trait-作为返回类型"><a href="#_2-5-实现-trait-作为返回类型" class="header-anchor">#</a> 2.5 实现 Trait 作为返回类型</h3> <ul><li>impl trait 语法
- <ul><li>注意:impl Trait 只能返回确定的同一种类型,返回可能不同类型的代码会报错</li></ul></li></ul> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">pub</span> <span class="token keyword">fn</span> <span class="token function-definition function">notify4</span><span class="token punctuation">(</span>flag<span class="token punctuation">:</span> <span class="token keyword">bool</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token keyword">impl</span> <span class="token class-name">Summary</span> <span class="token punctuation">{</span>
- <span class="token keyword">if</span> flag <span class="token punctuation">{</span>
- <span class="token class-name">NewsArticle</span> <span class="token punctuation">{</span><span class="token punctuation">...</span><span class="token punctuation">}</span>
- <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
- <span class="token class-name">Tweet</span> <span class="token punctuation">{</span><span class="token punctuation">...</span><span class="token punctuation">}</span>
- <span class="token punctuation">}</span>
- <span class="token punctuation">}</span>
- </code></pre></div><p>这样的话这个函数便没有了确定的返回类型,这样便会报错。</p> <h3 id="_2-6-使用-trait-bound-实现之前泛型-的例子"><a href="#_2-6-使用-trait-bound-实现之前泛型-的例子" class="header-anchor">#</a> 2.6 使用 trait bound 实现之前泛型 的例子</h3> <p>我们再来看一下<a href="#12-%E5%9C%A8%E5%87%BD%E6%95%B0%E5%AE%9A%E4%B9%89%E4%B8%AD%E4%BD%BF%E7%94%A8%E6%B3%9B%E5%9E%8B">之前的代码</a>。解决如下:</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">fn</span> <span class="token function-definition function">largest</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token punctuation">:</span> <span class="token class-name">PartialOrd</span><span class="token operator">></span><span class="token punctuation">(</span>list<span class="token punctuation">:</span> <span class="token operator">&</span><span class="token punctuation">[</span><span class="token class-name">T</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">T</span> <span class="token punctuation">{</span>
- <span class="token keyword">let</span> <span class="token keyword">mut</span> largest <span class="token operator">=</span> list<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
- <span class="token keyword">for</span> <span class="token operator">&</span>item <span class="token keyword">in</span> list <span class="token punctuation">{</span>
- <span class="token keyword">if</span> item <span class="token operator">></span> largest <span class="token punctuation">{</span>
- largest <span class="token operator">=</span> item<span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- <span class="token punctuation">}</span>
- largest
- <span class="token punctuation">}</span>
- </code></pre></div><p>之前我们说过,实际上比较大小的运算符是实现了 <code>std::cmp::PartialOrd</code> 这样一个 trait,因此我们需要指定实现这个 trait 的泛型才能进行大小比较。</p> <p>但是这样改完后又会出现一个问题:</p> <div class="language-rust extra-class"><pre class="language-rust"><code>➜ ~<span class="token operator">/</span><span class="token class-name">Code</span><span class="token operator">/</span>rust<span class="token operator">/</span>pattern git<span class="token punctuation">:</span><span class="token punctuation">(</span>master<span class="token punctuation">)</span> ✗ cargo run
- <span class="token class-name">Compiling</span> pattern v0<span class="token number">.1</span><span class="token punctuation">.</span><span class="token number">0</span> <span class="token punctuation">(</span><span class="token operator">/</span>home<span class="token operator">/</span>cherry<span class="token operator">/</span><span class="token class-name">Code</span><span class="token operator">/</span>rust<span class="token operator">/</span>pattern<span class="token punctuation">)</span>
- error<span class="token punctuation">[</span><span class="token constant">E0508</span><span class="token punctuation">]</span><span class="token punctuation">:</span> cannot <span class="token keyword">move</span> out of <span class="token keyword">type</span> `<span class="token punctuation">[</span><span class="token class-name">T</span><span class="token punctuation">]</span>`<span class="token punctuation">,</span> a non<span class="token operator">-</span>copy slice
- <span class="token operator">-</span><span class="token punctuation">-></span> src<span class="token operator">/</span>main<span class="token punctuation">.</span>rs<span class="token punctuation">:</span><span class="token number">10</span><span class="token punctuation">:</span><span class="token number">19</span>
- <span class="token operator">|</span>
- <span class="token number">10</span> <span class="token operator">|</span> <span class="token keyword">let</span> <span class="token keyword">mut</span> largest <span class="token operator">=</span> list<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
- <span class="token operator">|</span> <span class="token operator">^</span><span class="token operator">^</span><span class="token operator">^</span><span class="token operator">^</span><span class="token operator">^</span><span class="token operator">^</span><span class="token operator">^</span>
- <span class="token operator">|</span> <span class="token operator">|</span>
- <span class="token operator">|</span> cannot <span class="token keyword">move</span> out of here
- <span class="token operator">|</span> <span class="token keyword">move</span> occurs because `list<span class="token punctuation">[</span>_<span class="token punctuation">]</span>` has <span class="token keyword">type</span> `<span class="token class-name">T</span>`<span class="token punctuation">,</span> which does not implement the `<span class="token class-name">Copy</span>` <span class="token keyword">trait</span>
- <span class="token operator">|</span> help<span class="token punctuation">:</span> consider borrowing here<span class="token punctuation">:</span> `<span class="token operator">&</span>list<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span>`
- error<span class="token punctuation">[</span><span class="token constant">E0507</span><span class="token punctuation">]</span><span class="token punctuation">:</span> cannot <span class="token keyword">move</span> out of a shared reference
- <span class="token operator">-</span><span class="token punctuation">-></span> src<span class="token operator">/</span>main<span class="token punctuation">.</span>rs<span class="token punctuation">:</span><span class="token number">11</span><span class="token punctuation">:</span><span class="token number">18</span>
- <span class="token operator">|</span>
- <span class="token number">11</span> <span class="token operator">|</span> <span class="token keyword">for</span> <span class="token operator">&</span>item <span class="token keyword">in</span> list <span class="token punctuation">{</span>
- <span class="token operator">|</span> <span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span><span class="token operator">-</span> <span class="token operator">^</span><span class="token operator">^</span><span class="token operator">^</span><span class="token operator">^</span>
- <span class="token operator">|</span> <span class="token operator">||</span>
- <span class="token operator">|</span> <span class="token operator">|</span>data moved here
- <span class="token operator">|</span> <span class="token operator">|</span><span class="token keyword">move</span> occurs because `item` has <span class="token keyword">type</span> `<span class="token class-name">T</span>`<span class="token punctuation">,</span> which does not implement the `<span class="token class-name">Copy</span>` <span class="token keyword">trait</span>
- <span class="token operator">|</span> help<span class="token punctuation">:</span> consider removing the `<span class="token operator">&</span>`<span class="token punctuation">:</span> `item`
- <span class="token class-name">Some</span> errors have detailed explanations<span class="token punctuation">:</span> <span class="token constant">E0507</span><span class="token punctuation">,</span> <span class="token constant">E0508</span><span class="token punctuation">.</span>
- <span class="token class-name">For</span> more information about an error<span class="token punctuation">,</span> <span class="token keyword">try</span> `rustc <span class="token operator">-</span><span class="token operator">-</span>explain <span class="token constant">E0507</span>`<span class="token punctuation">.</span>
- error<span class="token punctuation">:</span> could not compile `pattern` due to <span class="token number">2</span> previous errors
- </code></pre></div><p>报错原因是:无法从 list 中移除 T,因为没有实现 Copy trait,建议采用借用</p> <p>因为上面两个 vector 中的元素分别为整型和字符型,这两种类型有确定的大小并且都是存储在栈中,因此都实现了 Copy trait,于是在 T 的 trait 约束中再加上 Copy 即可:</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">fn</span> <span class="token function-definition function">largest</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token punctuation">:</span> <span class="token class-name">PartialOrd</span> <span class="token operator">+</span> <span class="token class-name">Copy</span><span class="token operator">></span><span class="token punctuation">(</span>list<span class="token punctuation">:</span> <span class="token operator">&</span><span class="token punctuation">[</span><span class="token class-name">T</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">T</span> <span class="token punctuation">{</span>
- <span class="token keyword">let</span> <span class="token keyword">mut</span> largest <span class="token operator">=</span> list<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
- <span class="token keyword">for</span> <span class="token operator">&</span>item <span class="token keyword">in</span> list <span class="token punctuation">{</span>
- <span class="token keyword">if</span> item <span class="token operator">></span> largest <span class="token punctuation">{</span>
- largest <span class="token operator">=</span> item<span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- <span class="token punctuation">}</span>
- largest
- <span class="token punctuation">}</span>
- </code></pre></div><p>但是如果将 vec 中元素类型改为 String,那么又会报错,因为 String 是存储在堆中,没有实现 Copy trait,但是实现了 Clone trait</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">let</span> str_list <span class="token operator">=</span> <span class="token macro property">vec!</span><span class="token punctuation">[</span><span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"Hello"</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">::</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token string">"World"</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
- <span class="token keyword">let</span> largest <span class="token operator">=</span> <span class="token function">get_max_ele</span><span class="token punctuation">(</span><span class="token operator">&</span>str_list<span class="token punctuation">)</span><span class="token punctuation">;</span>
- </code></pre></div><p>我们将 T 加上 Clone 约束,去掉 Copy 约束:</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">fn</span> <span class="token function-definition function">get_max_ele</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token punctuation">:</span> <span class="token class-name">PartialOrd</span> <span class="token operator">+</span> <span class="token class-name">Clone</span><span class="token operator">></span><span class="token punctuation">(</span>list<span class="token punctuation">:</span> <span class="token operator">&</span><span class="token punctuation">[</span><span class="token class-name">T</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">T</span> <span class="token punctuation">{</span>
- <span class="token keyword">let</span> <span class="token keyword">mut</span> largest <span class="token operator">=</span> list<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
- <span class="token keyword">for</span> <span class="token operator">&</span>item <span class="token keyword">in</span> list <span class="token punctuation">{</span>
- <span class="token keyword">if</span> item <span class="token operator">></span> largest <span class="token punctuation">{</span>
- largest <span class="token operator">=</span> item<span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- <span class="token punctuation">}</span>
- largest
- <span class="token punctuation">}</span>
- </code></pre></div><p>这样又会出现错误:</p> <div class="language-rust extra-class"><pre class="language-rust"><code>error<span class="token punctuation">[</span><span class="token constant">E0508</span><span class="token punctuation">]</span><span class="token punctuation">:</span> cannot <span class="token keyword">move</span> out of <span class="token keyword">type</span> `<span class="token punctuation">[</span><span class="token class-name">T</span><span class="token punctuation">]</span>`<span class="token punctuation">,</span> a non<span class="token operator">-</span>copy slice
- <span class="token operator">-</span><span class="token punctuation">-></span> src<span class="token operator">/</span>main<span class="token punctuation">.</span>rs<span class="token punctuation">:</span><span class="token number">21</span><span class="token punctuation">:</span><span class="token number">23</span>
- <span class="token operator">|</span>
- <span class="token number">21</span> <span class="token operator">|</span> <span class="token keyword">let</span> <span class="token keyword">mut</span> largest <span class="token operator">=</span> list<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
- <span class="token operator">|</span> <span class="token operator">^</span><span class="token operator">^</span><span class="token operator">^</span><span class="token operator">^</span><span class="token operator">^</span><span class="token operator">^</span><span class="token operator">^</span>
- <span class="token operator">|</span> <span class="token operator">|</span>
- <span class="token operator">|</span> cannot <span class="token keyword">move</span> out of here
- <span class="token operator">|</span> <span class="token keyword">move</span> occurs because `list<span class="token punctuation">[</span>_<span class="token punctuation">]</span>` has <span class="token keyword">type</span> `<span class="token class-name">T</span>`<span class="token punctuation">,</span> which does not implement the `<span class="token class-name">Copy</span>` <span class="token keyword">trait</span>
- <span class="token operator">|</span> help<span class="token punctuation">:</span> consider borrowing here<span class="token punctuation">:</span> `<span class="token operator">&</span>list<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span>`
- </code></pre></div><p>是因为这里 list[0] 是字符串切片,是一个借用,没有所有权,因此一个借用给一个变量赋值,这个借用对应的类型必须要实现 Copy trait。因此在 list 前面加上引用,并且将 item 也设为引用,最后返回 &T。</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">fn</span> <span class="token function-definition function">get_max_ele</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token punctuation">:</span> <span class="token class-name">PartialOrd</span> <span class="token operator">+</span> <span class="token class-name">Clone</span><span class="token operator">></span><span class="token punctuation">(</span>list<span class="token punctuation">:</span> <span class="token operator">&</span><span class="token punctuation">[</span><span class="token class-name">T</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token operator">&</span><span class="token class-name">T</span> <span class="token punctuation">{</span>
- <span class="token keyword">let</span> <span class="token keyword">mut</span> largest <span class="token operator">=</span> <span class="token operator">&</span>list<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
- <span class="token keyword">for</span> item <span class="token keyword">in</span> list <span class="token punctuation">{</span>
- <span class="token keyword">if</span> item <span class="token operator">></span> largest <span class="token punctuation">{</span>
- largest <span class="token operator">=</span> item<span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- <span class="token punctuation">}</span>
- largest
- <span class="token punctuation">}</span>
- </code></pre></div><p>若要最后还是返回 T,则可以使用 clone 方法:</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">fn</span> <span class="token function-definition function">get_max_ele</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token punctuation">:</span> <span class="token class-name">PartialOrd</span> <span class="token operator">+</span> <span class="token class-name">Clone</span><span class="token operator">></span><span class="token punctuation">(</span>list<span class="token punctuation">:</span> <span class="token operator">&</span><span class="token punctuation">[</span><span class="token class-name">T</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token class-name">T</span> <span class="token punctuation">{</span>
- <span class="token keyword">let</span> <span class="token keyword">mut</span> largest <span class="token operator">=</span> list<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">clone</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token keyword">for</span> item <span class="token keyword">in</span> list <span class="token punctuation">{</span>
- <span class="token keyword">if</span> item <span class="token operator">></span> <span class="token operator">&</span>largest <span class="token punctuation">{</span>
- largest <span class="token operator">=</span> item<span class="token punctuation">.</span><span class="token function">clone</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- <span class="token punctuation">}</span>
- largest
- <span class="token punctuation">}</span>
- </code></pre></div><h3 id="_2-7-使用-trait-bound-有条件的实现方法"><a href="#_2-7-使用-trait-bound-有条件的实现方法" class="header-anchor">#</a> 2.7 使用 Trait Bound 有条件的实现方法</h3> <p>在使用泛型类型参数的 impl 块上使用 Trait bound,我们可以有条件的为实现了特定 Trait 的类型来实现方法</p> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">struct</span> <span class="token type-definition class-name">Pair</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token operator">></span> <span class="token punctuation">{</span>
- x<span class="token punctuation">:</span> <span class="token class-name">T</span><span class="token punctuation">,</span>
- y<span class="token punctuation">:</span> <span class="token class-name">T</span><span class="token punctuation">,</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">impl</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token operator">></span> <span class="token class-name">Pair</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token operator">></span> <span class="token punctuation">{</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">new</span><span class="token punctuation">(</span>x<span class="token punctuation">:</span> <span class="token class-name">T</span><span class="token punctuation">,</span> y<span class="token punctuation">:</span> <span class="token class-name">T</span><span class="token punctuation">)</span> <span class="token punctuation">-></span> <span class="token keyword">Self</span> <span class="token punctuation">{</span>
- <span class="token keyword">Self</span> <span class="token punctuation">{</span> x<span class="token punctuation">,</span> y <span class="token punctuation">}</span>
- <span class="token punctuation">}</span>
- <span class="token punctuation">}</span>
- <span class="token keyword">impl</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token punctuation">:</span> <span class="token class-name">Display</span> <span class="token operator">+</span> <span class="token class-name">PartialOrd</span><span class="token operator">></span> <span class="token class-name">Pair</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token operator">></span> <span class="token punctuation">{</span>
- <span class="token keyword">fn</span> <span class="token function-definition function">cmd_display</span><span class="token punctuation">(</span><span class="token operator">&</span><span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
- <span class="token keyword">if</span> <span class="token keyword">self</span><span class="token punctuation">.</span>x <span class="token operator">>=</span> <span class="token keyword">self</span><span class="token punctuation">.</span>y <span class="token punctuation">{</span>
- <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"The largest member is x = {}"</span><span class="token punctuation">,</span> <span class="token keyword">self</span><span class="token punctuation">.</span>x<span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
- <span class="token macro property">println!</span><span class="token punctuation">(</span><span class="token string">"The largest member is y = {}"</span><span class="token punctuation">,</span> <span class="token keyword">self</span><span class="token punctuation">.</span>y<span class="token punctuation">)</span><span class="token punctuation">;</span>
- <span class="token punctuation">}</span>
- <span class="token punctuation">}</span>
- <span class="token punctuation">}</span>
- </code></pre></div><ul><li>也可以为实现了其它 Trait 的任意类型有条件的实现某个 Trait</li> <li>为满足 Trait Bound 的所有类型上实现 Trait 叫做覆盖实现 (blanket implementations)</li></ul> <div class="language-rust extra-class"><pre class="language-rust"><code><span class="token keyword">impl</span><span class="token operator"><</span><span class="token class-name">T</span><span class="token punctuation">:</span> <span class="token namespace">fmt<span class="token punctuation">::</span></span><span class="token class-name">Display</span><span class="token operator">></span> <span class="token class-name">Tostring</span> <span class="token keyword">for</span> <span class="token class-name">T</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
- </code></pre></div><p>含义为:为实现了 Display trait 的类型实现 ToString trait,而 ToString 中实现了 to_string 方法。</p> <p>例如 <code>let s = 3.to_string();</code></p></div> <footer class="page-edit"><!----> <!----></footer> <!----> </main></div><div class="global-ui"></div></div>
- <script src="/rust_camp_tutorial/assets/js/app.d7ab8f65.js" defer></script><script src="/rust_camp_tutorial/assets/js/2.3dc1b8de.js" defer></script><script src="/rust_camp_tutorial/assets/js/1.7f771cfb.js" defer></script><script src="/rust_camp_tutorial/assets/js/31.e1aa8cbc.js" defer></script>
- </body>
- </html>
|