如何创建具有多个实例化选项的类

时间:2015-10-17 23:12:41

标签: rust

我想在Rust中构建一个类,它允许实例化的多样性和方便性,类似于std::net::TcpStream可以为其connect方法提供多个输入的方式。

我有以下测试,但我很少想到为实现这个结果而需要构建的结构或特征。

#[cfg(test)]
mod test {
    use super::Ipv4Network;
    use std::net::Ipv4Addr;

    #[test]
    fn instantiation() {
        let net_addr = Ipv4Addr::new(10, 0, 0, 0);
        let net_mask = Ipv4Addr::new(255, 255, 255, 240);

        // Instantiate an Ipv4Network using two Ipv4Addrs.
        let with_addrs = Ipv4Network::new(net_addr, net_mask);

        // Instantiate an Ipv4Network using an Ipv4Addr and a prefix integer.
        let with_addr_prefix = Ipv4Network::new(net_addr, 28);

        // Instantiate an Ipv4Network using two strings.
        let with_strings = Ipv4Network::new("10.0.0.0", "255.255.255.240");

        // Instantiate an Ipv4Network using a string and a prefix integer.
        let with_prefix = Ipv4Network::new("10.0.0.0", 28);

        // Instantiate an Ipv4Network using a string with CIDR notation.
        let with_cidr = Ipv4Network::new("10.0.0.0/28");
    }
}

我的理解是std::net::TcpStream通过ToSocketAddrs特征完成了多个connect输入,其来源可以找到here。究竟std::net:TcpStream::connect uses ToSocketAddrs对我来说并不清楚,但我想我应该能够如下定义Ipv4Network

pub struct Ipv4Network {
    addr: Ipv4Addr,
    mask: Ipv4Addr,
}

如果这是真的,那么我该如何创建像ToIpv4Network这样的函数为ToSocketAddrs创建特征(比如std::net:TcpStream)?

的内容应该是什么?
impl ToIpv4Network for (Ipv4Addr, Ipv4Addr) {
...
}
看起来像?这是开始下降的正确道路吗?

1 个答案:

答案 0 :(得分:1)

这是一个合理的工作场所。我认为您的一个问题是您定义的接口很难通过使用特征来完成。

所以,让我们谈谈ToSocketAddrs的工作方式。首先,让我们快速记下,然后忽略ToSocketAddrs特征返回Iterator SocketAddrs的事实。我们忽略了它,因为它实际上与手头的问题无关。

这是特质声明的主体:

pub trait ToSocketAddrs {
    type Iter: Iterator<Item=SocketAddr>;
    fn to_socket_addrs(&self) -> Result<Self::Iter>;
}

此特征的目的是允许它在通用函数/结构中用作trait bound。从广义上讲,特征边界是编写泛型的一种方式,但是获取Rust编译器以确保最终实例化泛型的类型实现由该特征(或特征)定义的行为。

对于ToSocketAddrs,这意味着类型可以(可能)转换为SocketAddr。在connect内部调用的代码然后使用在特征上定义的to_socket_addrs函数。

简单地说,我可能会因为to_socket_addrs返回一个Result来表示Ok(<success-type>)Err(<failure-type>)的值,这可能是一个很好的模型模型你的特质。

这是关键为什么我认为你想要的界面可能不理想(或可实现,Rust不直接支持arity,或任何其他类型的函数重载)。传递特征绑定通用参数是实现目标的最简单方法。