我想在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) {
...
}
看起来像?这是开始下降的正确道路吗?
答案 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,或任何其他类型的函数重载)。传递特征绑定通用参数是实现目标的最简单方法。