rust学习二十.8、RUST特质的限定,实为对类型的限定
<p>有的时候,可能希望使用的特质已经实现了其它特质(看后面可以知道,实际是要求相关类型实现了其它特质)。</p><p>RUST支持为特质(trait)指定限定的特质。</p>
<p><strong>例如我们定义特质A,之后定义了类型T,这个时候还希望T已经实现了特质TC</strong>。</p>
<p>在rust中就是这个语法:</p>
<p>trait tx:t1</p>
<p>trait tx:t1+t2..+tn</p>
<p>根据相关数据的例子和说明,需要特别注意,具体的实现都是依赖于类型,而不是特质。</p>
<h1>一、示例1</h1>
<pre class="language-rust highlighter-hljs"><code>use std::fmt;
struct Point {
x: i32,
y: i32,
}
trait Copy{
fn copy(&self) -> Self;
}
trait OutlinePrint: fmt::Display+Copy{
fn outline_print(&self) {
let output = self.to_string();
let len = output.len();
println!("{}", "*".repeat(len + 4));
println!("*{}*", " ".repeat(len + 2));
println!("* {output} *");
println!("*{}*", " ".repeat(len + 2));
println!("{}", "*".repeat(len + 4));
}
}
impl OutlinePrint for Point {}
impl fmt::Display for Point {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
impl Copy for Point {
fn copy(&self) -> Self {
Point { x: self.x, y: self.y }
}
}
fn main() {
let p = Point { x: 10, y: 20 };
p.outline_print();
let c=p.copy();
c.outline_print();
}</code></pre>
<p>在本例中Point必须实现特质Copy和Display和OutlinePrint,注意OutlinePrint的定义:</p>
<p><code>trait OutlinePrint: fmt::Display+Copy</code></p>
<p>多个特质之间用+号连接。</p>
<p>输出如下:</p>
<p><img src="https://img2024.cnblogs.com/blog/1177268/202503/1177268-20250331171047299-1603418764.png"></p>
<p> </p>
<h1>二、示例2-在方法中使用特质有关方法</h1>
<p>把以上的例子稍微修改下:</p>
<pre class="language-rust highlighter-hljs"><code>use std::fmt;
struct Point {
x: i32,
y: i32,
}
trait Copyable {
fn copy(&self) -> Self;
}
trait OutlinePrint: fmt::Display + Copyable +Sized{
fn outline_print(&self) {
// 先创建副本
let copied = self.copy();
// 然后将副本转换为字符串
let output = copied.to_string();
let len = output.len();
println!("{}", "*".repeat(len + 4));
println!("*{}*", " ".repeat(len + 2));
println!("* {} *", output);
println!("*{}*", " ".repeat(len + 2));
println!("{}", "*".repeat(len + 4));
}
}
impl OutlinePrint for Point {}
impl fmt::Display for Point {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
impl Copyable for Point {
fn copy(&self) -> Self {
Point { x: self.x, y: self.y }
}
}
fn main() {
let p = Point { x: 10, y: 20 };
p.outline_print();
}</code></pre>
<p>本例中,首先为OutlinePrint增加一个限定Sized,其次方法outline_print是先copy再to_string.</p>
<p>如果OutlinePrint不添加一个Sized,那么会提示语句 let copied=self.copy()报错:doesn't have a size known at compile-time</p>
<p>rustc的给出的建议是:fn outline_print(&self) where Self: Sized ,即为方法outline_print的参数添加限定(这是我们习惯的方式)</p>
<p><strong>为什么Point不需要实现Sized?这是因为Point的大小是确定的,其次编译器会为此类类型隐式实现</strong>。</p>
<p>输出略。</p>
<h1>三、示例3-如果不使用特质的限定</h1>
<p>由于可以为方法的参数进行限定,我们很容易想到其实可以只对参数限定即可。</p>
<p>为了节约篇幅,这里只把核心的内容贴出:</p>
<pre class="language-rust highlighter-hljs"><code>trait OutlinePrint{
fn outline_print(&self)
where Self: fmt::Display + Copyable+Sized
{
// 先创建副本
let copied = self.copy();
// 然后将副本转换为字符串
let output = copied.to_string();
let len = output.len();
println!("{}", "*".repeat(len + 4));
println!("*{}*", " ".repeat(len + 2));
println!("* {} *", output);
println!("*{}*", " ".repeat(len + 2));
println!("{}", "*".repeat(len + 4));
}
}</code></pre>
<p>输出:</p>
<p><img src="https://img2024.cnblogs.com/blog/1177268/202503/1177268-20250331173829042-694921395.png"></p>
<h1>四、小结</h1>
<p>这种定义方式个人认为不是很符合一般思维方式,这是因为明明是对类型的限制,但是这种限制确写在特质上。</p>
<p>例如在java等语言中,就没有这种方式。</p>
<p>个人更加倾向于采用示例3的方式,尤其是在接触多了类似JAVA之类的OOP语言后。</p>
<p> </p>
<p>当然rust这种定义方式也有优点:如果相关特质方法的参数都是这种要求,那么写在特质上,的确会少打一些字。</p>
<p>所以,rust程序员可以根据需要来决定限定方式,某种程度上rust为我们提供了方便性和灵活性。</p>
<p> </p>
</div>
<div id="MySignature" role="contentinfo">
<p>本文来自博客园,作者:正在战斗中,转载请注明原文链接:https://www.cnblogs.com/lzfhope/p/18802354</p><br><br>
来源:https://www.cnblogs.com/lzfhope/p/18802354
頁:
[1]