為什么Rust不支持特征對(duì)象向上轉(zhuǎn)換?
為什么Rust不支持特征對(duì)象向上轉(zhuǎn)換?鑒于此代碼:trait Base {
fn a(&self);
fn b(&self);
fn c(&self);
fn d(&self);}trait Derived : Base {
fn e(&self);
fn f(&self);
fn g(&self);}struct S;impl Derived for S {
fn e(&self) {}
fn f(&self) {}
fn g(&self) {}}impl Base for S {
fn a(&self) {}
fn b(&self) {}
fn c(&self) {}
fn d(&self) {}}這是為什么?該Derived虛函數(shù)表必須引用Base在這樣或那樣的方法。檢查L(zhǎng)LVM IR顯示以下內(nèi)容:@vtable4 = internal unnamed_addr constant {
void (i8*)*,
i64,
i64,
void (%struct.S*)*,
void (%struct.S*)*,
void (%struct.S*)*,
void (%struct.S*)*} {
void (i8*)* @_ZN2i813glue_drop.98717h857b3af62872ffacE,
i64 0,
i64 1,
void (%struct.S*)* @_ZN6S.Base1a20h57ba36716de00921jbaE,
void (%struct.S*)* @_ZN6S.Base1b20h3d50ba92e362d050pbaE,
void (%struct.S*)* @_ZN6S.Base1c20h794e6e72e0a45cc2vbaE,
void (%struct.S*)* @_ZN6S.Base1d20hda31e564669a8cdaBbaE}@vtable26 = internal unnamed_addr constant {
void (i8*)*,
i64,
i64,
void (%struct.S*)*,
void (%struct.S*)*,
void (%struct.S*)*,
void (%struct.S*)*,
void (%struct.S*)*,
void (%struct.S*)*,
void (%struct.S*)*} {
void (i8*)* @_ZN2i813glue_drop.98717h857b3af62872ffacE,
i64 0,
i64 1,所有Rust vtable都包含指向第一個(gè)字段中的析構(gòu)函數(shù),大小和對(duì)齊的指針,并且子引用vtable在引用supertrait方法時(shí)不會(huì)復(fù)制它們,也不會(huì)使用對(duì)supertrait vtables的間接引用。他們只是逐字地?fù)碛蟹椒ㄖ羔樀母北径鴽](méi)有別的。鑒于這種設(shè)計(jì),很容易理解為什么這不起作用。需要在運(yùn)行時(shí)構(gòu)建一個(gè)新的vtable,它可能存在于堆棧中,這并不是一個(gè)優(yōu)雅(或最佳)的解決方案。當(dāng)然,有一些解決方法,比如在界面中添加顯式的upcast方法,但這需要相當(dāng)多的樣板(或宏觀狂熱)才能正常工作。現(xiàn)在,問(wèn)題是 - 為什么不能以某種方式實(shí)現(xiàn)特征對(duì)象向上轉(zhuǎn)換?比如,在subtrait的vtable中添加指向supertrait的vtable的指針。目前,Rust的動(dòng)態(tài)調(diào)度似乎不滿足Liskov替換原則,這是面向?qū)ο笤O(shè)計(jì)的一個(gè)非?;镜脑瓌t。當(dāng)然你可以使用靜態(tài)調(diào)度,這在Rust中使用確實(shí)非常優(yōu)雅,但它很容易導(dǎo)致代碼膨脹,這有時(shí)比計(jì)算性能更重要 - 比如在嵌入式系統(tǒng)上,而Rust開(kāi)發(fā)人員聲稱支持這樣的用例。語(yǔ)言。此外,在許多情況下,您可以成功使用一個(gè)非純粹面向?qū)ο蟮哪P?,這似乎是Rust的功能設(shè)計(jì)所鼓勵(lì)的。盡管如此,Rust支持許多有用的OO模式......那么為什么不使用LSP呢?有誰(shuí)知道這種設(shè)計(jì)的理由?
查看完整描述