函數(shù)很好,但是如果你想要在一些數(shù)據(jù)上調(diào)用很多函數(shù),那是非常不合適的。請(qǐng)思考以下代碼:
baz(bar(foo)));
我們從左往右讀這些代碼,就會(huì)看到 ‘baz bar foo’。但是這并不是我們由內(nèi)-外調(diào)用函數(shù)的順序:‘foo bar baz’。如果我們這樣寫(xiě),會(huì)不會(huì)更好?
foo.bar().baz();
幸運(yùn)的是,你可能已經(jīng)猜到了,關(guān)于上面問(wèn)題的答案,可以! Rust 提供了一種可以通過(guò) impl 關(guān)鍵字來(lái)使用‘方法調(diào)用語(yǔ)法’的能力。
以下代碼展示了它是怎樣工作的:
struct Circle {
x: f64,
y: f64,
radius: f64,
}
impl Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.radius * self.radius)
}
}
fn main() {
let c = Circle { x: 0.0, y: 0.0, radius: 2.0 };
println!("{}", c.area());
}
以上代碼將打印 12.566371。
我們已經(jīng)建了一個(gè)表示一個(gè)圓的結(jié)構(gòu)體。然后我們寫(xiě)一個(gè) impl 塊,同時(shí)我們?cè)趬K中定義一個(gè)方法,area。
方法使用一個(gè)特殊的第一參數(shù),其中有三個(gè)變量:self,&self 和 &mut self。你可以將這個(gè)第一參數(shù)想象成 foo.bar() 中的 foo。這三種變量對(duì)應(yīng)于 foo 可能成為的三種東西:如果它只是堆棧中的一個(gè)值使用 self,如果它是一個(gè)引用使用 &self,如果它是一個(gè)可變引用使用 &mut self。因?yàn)槲覀兪褂昧?&self作為 area 的參數(shù),我們可以像其他參數(shù)一樣使用它。由于我們知道它是一個(gè) Circle,我們可以像訪問(wèn)其它結(jié)構(gòu)體一樣,訪問(wèn) radius。
我們應(yīng)默認(rèn)使用 &self,同時(shí)相對(duì)于取得所有權(quán),你應(yīng)該更傾向于借用,以及使用不可變的引用來(lái)頂替可變的引用。以下是關(guān)于所有三個(gè)變量的一個(gè)例子:
struct Circle {
x: f64,
y: f64,
radius: f64,
}
impl Circle {
fn reference(&self) {
println!("taking self by reference!");
}
fn mutable_reference(&mut self) {
println!("taking self by mutable reference!");
}
fn takes_ownership(self) {
println!("taking ownership of self!");
}
}
所以,至此我們知道了怎樣去調(diào)用一個(gè)方法,諸如 foo.bar()。但是我們?cè)瓉?lái)的例子 foo.bar().baz() 的例子怎么辦?這就是所謂的‘方法鏈接’,我們可以通過(guò)返回 self 來(lái)完成它。
struct Circle {
x: f64,
y: f64,
radius: f64,
}
impl Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.radius * self.radius)
}
fn grow(&self, increment: f64) -> Circle {
Circle { x: self.x, y: self.y, radius: self.radius + increment }
}
}
fn main() {
let c = Circle { x: 0.0, y: 0.0, radius: 2.0 };
println!("{}", c.area());
let d = c.grow(2.0).area();
println!("{}", d);
}
檢查返回類(lèi)型:
fn grow(&self) -> Circle {
我們只是說(shuō)我們返回了一個(gè) Circle。通過(guò)這個(gè)方法,我們可以將一個(gè)新的圓圈增加到任意大小。
你還可以定義一個(gè)不使用 self 作為參數(shù)的關(guān)聯(lián)函數(shù)。以下代碼是在 Rust 代碼中非常常見(jiàn)的一種模式:
struct Circle {
x: f64,
y: f64,
radius: f64,
}
impl Circle {
fn new(x: f64, y: f64, radius: f64) -> Circle {
Circle {
x: x,
y: y,
radius: radius,
}
}
}
fn main() {
let c = Circle::new(0.0, 0.0, 2.0);
} #
這個(gè)‘關(guān)聯(lián)函數(shù)’為我們生成一個(gè)新的 Circle。請(qǐng)注意,關(guān)聯(lián)函數(shù)被 Struct::function() 語(yǔ)法調(diào)用,而不是 ref.method() 語(yǔ)法。其他一些語(yǔ)言稱(chēng)關(guān)聯(lián)函數(shù)為‘靜態(tài)方法’。
假如我們想要我們的用戶(hù)能夠創(chuàng)建 Circles,但是我們只允許他們?cè)O(shè)置他們關(guān)心的屬性。否則,x 和 y 的屬性將會(huì)是 0.0,同時(shí) radius 為 1.0。Rust 沒(méi)有方法重載,參數(shù)命名或者變量參數(shù)。我們使用生成器模式來(lái)代替它。如以下代碼所示:
struct Circle {
x: f64,
y: f64,
radius: f64,
}
impl Circle {
fn area(&self) -> f64 {
std::f64::consts::PI * (self.radius * self.radius)
}
}
struct CircleBuilder {
x: f64,
y: f64,
radius: f64,
}
impl CircleBuilder {
fn new() -> CircleBuilder {
CircleBuilder { x: 0.0, y: 0.0, radius: 1.0, }
}
fn x(&mut self, coordinate: f64) -> &mut CircleBuilder {
self.x = coordinate;
self
}
fn y(&mut self, coordinate: f64) -> &mut CircleBuilder {
self.y = coordinate;
self
}
fn radius(&mut self, radius: f64) -> &mut CircleBuilder {
self.radius = radius;
self
}
fn finalize(&self) -> Circle {
Circle { x: self.x, y: self.y, radius: self.radius }
}
}
fn main() {
let c = CircleBuilder::new()
.x(1.0)
.y(2.0)
.radius(2.0)
.finalize();
println!("area: {}", c.area());
println!("x: {}", c.x);
println!("y: {}", c.y);
}
我們這里所做的就是建立了另一個(gè)結(jié)構(gòu)體,CircleBuilder。我們已經(jīng)對(duì)它定義了我們的生成器方法。我們也已經(jīng)在 Circle 上定義了我們的 area() 方法。我們又在 CircleBuilder 上定義了另一方法:finalize()。這個(gè)方法從生成器中創(chuàng)建了我們的最后的 Circle?,F(xiàn)在,我們已經(jīng)使用類(lèi)型系統(tǒng)來(lái)強(qiáng)化我們關(guān)心的事情:我們可以使用在 CircleBuilder 上的方法來(lái)限制以我們選擇的任何方式制作 Circle。
更多建議: