前言
學(xué)習(xí)rust當(dāng)中遇到了這個(gè)問題,記錄一下,不對(duì)地方望指正
一、多態(tài)
多態(tài)是面向?qū)ο蟪绦蛟O(shè)計(jì)中的一個(gè)重要概念,指同一個(gè)行為或操作在不同實(shí)例上具有不同的行為或結(jié)果。簡單來說,多態(tài)就是指同一種類型的對(duì)象,在不同的上下文中有不同的行為。多態(tài)性使得程序可以更加靈活、可擴(kuò)展和易于維護(hù)。在實(shí)現(xiàn)多態(tài)性時(shí),通常會(huì)使用繼承、接口、抽象類等技術(shù)
二、rust實(shí)現(xiàn)多態(tài)
trait的靜態(tài)方式
trait Animal {
fn make_sound(&self);
}
struct Cat {}
impl Animal for Cat {
fn make_sound(&self) {
println!("Meow");
}
}
struct Dog {}
impl Animal for Dog {
fn make_sound(&self) {
println!("Woof");
}
}
fn main() {
let cat: Cat = Cat {};
let dog: Dog = Dog {};
test(cat);
test(dog)
}
//接受Animal Trait類型的
fn test(animal : impl Animal){
animal.make_sound()
}
定義了方法傳入?yún)?shù)是trait。這一種在實(shí)例化的時(shí)候是具體的類型,在傳參的時(shí)候編譯器能推斷出來具體是cat還是dog,能調(diào)用具體方法
還有一種方式可以通過動(dòng)態(tài)分發(fā),還以上面那段代碼,比如
trait Animal {
fn make_sound(&self);
}
struct Cat {}
impl Animal for Cat {
fn make_sound(&self) {
println!("Meow");
}
}
struct Dog {}
impl Animal for Dog {
fn make_sound(&self) {
println!("Woof");
}
}
fn main() {
let cat: Box<dyn Animal> = Box::new(Cat {});
let dog: Box<dyn Animal> = Box::new(Dog {});
test(cat);
test(dog)
}
fn test(animal: Box<dyn Animal>) {
animal.make_sound()
}
這種方式相對(duì)于上面更加靈活,因?yàn)閷?shí)例化參數(shù)變量類型是trait類型。現(xiàn)在說說關(guān)鍵點(diǎn)
dyn關(guān)鍵字
dyn關(guān)鍵字是在Rust中用于創(chuàng)建和使用動(dòng)態(tài)分發(fā)的trait對(duì)象的關(guān)鍵字。trait對(duì)象允許我們以統(tǒng)一的方式處理不同類型的對(duì)象,并使用相同的方法調(diào)用語法。使用動(dòng)態(tài)分發(fā),編譯器無需在編譯時(shí)知道具體的類型,而是在運(yùn)行時(shí)根據(jù)對(duì)象的實(shí)際類型來確定要調(diào)用的方法。要?jiǎng)?chuàng)建一個(gè)trait對(duì)象,需要在trait名稱前加上dyn關(guān)鍵字。例如,對(duì)于名為TraitName的trait,我們可以使用dyn TraitName來創(chuàng)建一個(gè)trait對(duì)象。
trait TraitName {
// trait定義
}
fn main() {
let trait_obj: Box<dyn TraitName> = Box::new(ConcreteType);
// 在這里使用trait對(duì)象
}
在上面的代碼中,trait_obj是一個(gè)Box指向動(dòng)態(tài)分發(fā)的trait對(duì)象的指針。它可以存儲(chǔ)實(shí)現(xiàn)了TraitName trait的任何具體類型的對(duì)象。通過dyn關(guān)鍵字,我們可以在運(yùn)行時(shí)根據(jù)實(shí)際類型來調(diào)用trait定義的方法。
這里要注意,trait對(duì)象通過指針或引用來操作,因此通常結(jié)合使用Box、&或&mut來創(chuàng)建和使用trait對(duì)象。為了在運(yùn)行時(shí)確定對(duì)象的大小,我們需要將它們放置在一個(gè)固定大小的容器中。這就是為什么要使用Box來包裝trait對(duì)象的原因。Box類型表示一個(gè)動(dòng)態(tài)分發(fā)的trait對(duì)象。它在堆上分配一塊內(nèi)存,該內(nèi)存用于存儲(chǔ)對(duì)象的數(shù)據(jù),并提供一個(gè)指向虛函數(shù)表(vtable)的指針,該表用于在運(yùn)行時(shí)查找和調(diào)用正確的方法。
這種方式相對(duì)于靜態(tài)方式會(huì)更加靈活,但會(huì)有運(yùn)行時(shí)性能損失,看情況決定使用哪一種
泛型方式
use std::fmt::{Display, Formatter};
struct Cat {}
struct Dog {}
impl Display for Cat{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f,"Cat")
}
}
impl Display for Dog{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f,"Dog")
}
}
fn make_sound<T: Display>(animal: T) {
println!("{}", animal);
}
fn main() {
make_sound(Cat{});
make_sound(Dog{});
}
通過在函數(shù)簽名中使用泛型類型參數(shù),函數(shù)可以接受不同類型的參數(shù),并在編譯時(shí)生成對(duì)應(yīng)的具體化代碼。這種方式不依賴于trait,而是基于類型推斷和編譯時(shí)的靜態(tài)分發(fā)
枚舉方式
還有一種方式是使用枚舉方式,例如
enum Shape {
Circle(f64),
Square(f64),
Rectangle(f64, f64),
}
impl Shape {
fn area(&self) -> f64 {
match *self {
Shape::Circle(radius) => std::f64::consts::PI * radius * radius,
Shape::Square(side_length) => side_length * side_length,
Shape::Rectangle(length, width) => length * width,
}
}
}
fn main() {
let circle = Shape::Circle(5.0);
let square = Shape::Square(4.0);
let rectangle = Shape::Rectangle(3.0, 6.0);
test(circle);
test(square);
test(rectangle);
}
fn test(shape: Shape) {
println!("shape area: {}", shape.area());
}
枚舉在實(shí)現(xiàn)多態(tài)性方面有一些優(yōu)點(diǎn)和缺點(diǎn)。以下是其中的一些:
優(yōu)點(diǎn):
簡潔性:枚舉提供了一種緊湊的方式來定義和組織具有不同變體的數(shù)據(jù)類型。它能夠在一個(gè)地方集中描述和管理多種可能的狀態(tài)或情況。
靜態(tài)類型檢查:由于枚舉的變體是預(yù)先定義的,編譯器可以在編譯時(shí)驗(yàn)證變體的正確性。這可以幫助捕捉到潛在的錯(cuò)誤,并提供類型安全性。
模式匹配:枚舉與模式匹配相結(jié)合,可以使代碼更具表達(dá)力和可讀性。模式匹配可以根據(jù)具體的變體類型執(zhí)行相應(yīng)的邏輯,同時(shí)處理所有可能的情況,避免遺漏。
缺點(diǎn):
限制的擴(kuò)展性:當(dāng)需要添加新的變體時(shí),枚舉需要進(jìn)行修改。這可能涉及到修改已有的代碼,以適應(yīng)新的變體。這對(duì)于外部庫或包的枚舉類型來說尤其困難,因?yàn)闊o法直接修改其定義。
冗余的結(jié)構(gòu):枚舉的每個(gè)變體都可以存儲(chǔ)不同的數(shù)據(jù)結(jié)構(gòu),這可能會(huì)導(dǎo)致某些變體擁有與其他變體不相關(guān)的冗余數(shù)據(jù)。這可能會(huì)浪費(fèi)內(nèi)存空間,尤其是當(dāng)只使用其中的一部分變體時(shí)。
靈活性的限制:枚舉要求提前定義所有可能的變體。如果需要在運(yùn)行時(shí)動(dòng)態(tài)添加新的變體,或者處理不確定的類型集合,那么枚舉可能不適合。文章來源:http://www.zghlxwxcb.cn/news/detail-677376.html
總結(jié)
以上就是今天要說的內(nèi)容,不對(duì)的地方望指正文章來源地址http://www.zghlxwxcb.cn/news/detail-677376.html
到了這里,關(guān)于【rust語言】rust多態(tài)實(shí)現(xiàn)方式的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!