Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
October 16, 2021 07:04 pm GMT

How to overload method in Rust (amount of args differ).

Adapt version

$ rustc --versionrustc 1.55.0 (c8dfcfe04 2021-09-06)

If you want to overload methods that have different amount of args likes following

// Constructor with 2 args.fn new(arg0, arg1) -> Self {    ...}// Constructor with 1 arg.fn new(arg) -> Self {    ...}

Macro is your better friend.

So macro can be used for pseud-overloading.

Pseud-overloading with macro.

struct SampleStruct {    ip_address: IpAddr,    port_number: u16,    sample_socket: socket2::Socket,}macro_rules! SampleStruct_new {    ($str_ip:expr , $num_port:expr) => ({        let ip: IpAddr = $str_ip.parse::<IpAddr>()            .unwrap_or_else( |_| { panic!("`address` MUST be an IPv4 address or IPv6 address.") });        SampleStruct {            ip_address: ip,            port_number: $num_port,            sample_socket: Socket::new(                if ip.is_ipv4() { Domain::IPV4 } else { Domain::IPV6 },                Type::DGRAM,                Some(Protocol::UDP)            ).unwrap()        }    });    ($obj_SocketAddr:expr) => ({        SampleStruct {            ip_address: $obj_SocketAddr.ip(),            port_number: $obj_SocketAddr.port(),            sample_socket: Socket::new(                if $obj_SocketAddr.ip().is_ipv4() { Domain::IPV4 } else { Domain::IPV6 },                Type::DGRAM,                Some(Protocol::UDP)            ).unwrap()        }    });}

Then it uses as following:

fn main() {    let foo = SampleStruct_new!("127.0.0.1", 12345);    println!("IP address = {}, Port = {}", foo.ip_address.to_string(), foo.port_number);    let ipv6_sock_addr = SocketAddr::new("::1".parse::<IpAddr>().unwrap(), 12345);    let bar = SampleStruct_new!(ipv6_sock_addr);    println!("IP address = {}, Port = {}", bar.ip_address.to_string(), bar.port_number);}

To see a sample code, go Rust playground

Generics with placeholder.

Generics with placeholder is also your frind. _:() in impl block means "this is unused argument".

trait SampleTrait<T, O> {    fn new(address:T, port:O) -> SampleStruct;}impl SampleTrait<&str, u16> for SampleStruct {    fn new(address: &str, port: u16) -> Self {        let addr = address.to_string().parse::<IpAddr>()            .unwrap_or_else( |_| { panic!("`address` MUST be an IPv4 address (dotted-decimal form) or an IPv6 address.") });        return SampleStruct {            ip_address: addr,            port_number: port,            sample_socket: Socket::new(                if addr.is_ipv4() { Domain::IPV4 } else { Domain::IPV6 },                Type::DGRAM,                Some(Protocol::UDP)            ).unwrap()        }    }}impl SampleTrait<SocketAddr, ()> for SampleStruct {    fn new(address: SocketAddr, _:()) -> Self {        return SampleStruct {            ip_address: address.ip(),            port_number: address.port(),            sample_socket: Socket::new(                if address.ip().is_ipv4() { Domain::IPV4 } else { Domain:: IPV6 },                Type::DGRAM,                Some(Protocol::UDP)            ).unwrap()        }    }}

When calling fn new(address: SocketAddr, _:()), the () MUST be passed to unused args. So it seems slightly ugly in this way.

fn main() {    let foo = SampleStruct::new("127.0.0.1".to_string(), 12345);    println!("IP address = {}, Port = {}", foo.ip_address.to_string(), foo.port_number);    let ipv6_sock_addr = SocketAddr::new("::1".parse::<IpAddr>().unwrap(), 12345);    let baz = SampleStruct::new(ipv6_sock_addr, ());    println!("IP address = {}, Port = {}", baz.ip_address.to_string(), baz.port_number);}

To see a sample code, go Rust playground


Original Link: https://dev.to/fmtweisszwerg/how-to-overload-method-in-rust-amount-of-args-differ-48id

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To