允许通过特征组合符合预定义API的不同对象

问题描述 投票:0回答:1

我们如何允许符合预定义 API 的不同对象的组合?我尝试做的一种方法是通过使用特质中的特质但失败了,我的尝试

pub trait XAPI {
    fn new(y: YAPI) -> Self;
}

pub trait YAPI {
    fn new() -> Self;
}

pub struct X {
}

pub struct Y {
}

impl YAPI for Y{
    fn new() -> Self {
        Y {}
    }
}
impl XAPI for X{
    fn new(y: YAPI) -> Self {
        X {}
    }
}

这在 Rust 中可能吗?

Java 具体示例

/* Online Java Compiler and Editor */
interface PocketAPI {}

class Pocket implements PocketAPI {}

interface JacketAPI {}

class Jacket implements JacketAPI {

  public Jacket(PocketAPI labelStore) {}
}

public class Main {
  public static void main(String[] args) {
    System.out.println("!!!");

    PocketAPI pocket = new Pocket();

    JacketAPI jacket = new Jacket(pocket);
  }
}
oop rust traits
1个回答
0
投票

在Java中,所有对象都经过引用计数并存在于堆中。因此很容易获得它们的接口引用。

在 Rust 中,默认情况下值存在于堆栈中,并且不能转换为特征对象,因为特征对象的大小未知。它们不携带底层对象有多大的信息。

这意味着您需要创建对特征对象的大小引用;这可以通过两种方式完成:引用或作为堆对象 (

Box
)。

为了接近 Java 代码,我会使用

Box
:

pub trait XAPI {
    fn new(y: Box<dyn YAPI>) -> Self;
}

pub trait YAPI {
    fn new() -> Self;
}

pub struct X {}

pub struct Y {}

impl YAPI for Y {
    fn new() -> Self {
        Y {}
    }
}
impl XAPI for X {
    fn new(y: Box<dyn YAPI>) -> Self {
        X {}
    }
}

然而,这给我们带来了一个新问题;现在它说 '

YAPI
无法制作成对象'。这是真的,因为
YAPI
有一个静态函数(不包含
self
),这消除了它的 对象安全性

原因有些复杂;简而言之,Rust 只能确定特征引用后面确实有一个对象,才能确定哪个对象位于该特征引用后面。然后它使用

self
引用来决定它是哪个对象(v 表和其他东西)。但是,如果您在对 YAPI 的特征引用上调用
new
,编译器将不知道要调用哪个函数,因为没有
self
连接到该调用。

因此,如果您从

new()
中删除
YAPI
,它将按预期工作:

pub trait XAPI {
    fn new(y: Box<dyn YAPI>) -> Self;
}

pub trait YAPI {}

pub struct X {}

pub struct Y {}

impl Y {
    fn new() -> Self {
        Y {}
    }
}

impl YAPI for Y {}

impl XAPI for X {
    fn new(y: Box<dyn YAPI>) -> Self {
        X {}
    }
}

fn main() {
    let y = Box::new(Y::new());
    let x = X::new(y);
}
© www.soinside.com 2019 - 2024. All rights reserved.