Rust で関数・メソッドをオーバーロード (多重定義) する方法 その1
Tags: rust, programming, japanese
Published: 2021-10-14 17:23:00

---
title: Rust で関数・メソッドをオーバーロード (多重定義) する方法 その1
published: true
description: Rust で関数・メソッドの引数の「数が同じ」で「型が異なる」場合にオーバーロードする方法
tags: rust, programming, Japanese,
//cover_image: https://direct_url_to_image.jpg
---

対象バージョン

```
$ rustc --version
rustc 1.55.0 (c8dfcfe04 2021-09-06)
```

今回は最も簡単な 引数の「数が同じ」で「型が異なる」場合に関数をオーバーロードする方法です。

この場合はジェネリクスを使用します。

下記の例では `SampleStruct::new()` をオーバーロードすることで複数の異なる型に対応できるようにしています。(return はなくてもよいのですが、他言語を使用する方にも理解しやすくするためにあえて使用しています)

```rust
use std::net:: {
    IpAddr,
    SocketAddr,
};

use socket2:: {
    Domain,
    Protocol,
    Socket,
    Type,
};

struct SampleStruct {
    ip_address: IpAddr,
    port_number: u16,
    sample_socket: socket2::Socket,
}

trait SampleTrait<T, O> {
    fn new(address:T, port:O) -> SampleStruct;
}

impl SampleTrait<String, u16> for SampleStruct {
    fn new(address: String, port: u16) -> Self {
        let addr = address.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<&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<IpAddr, u16> for SampleStruct {
    fn new(address: IpAddr, port: u16) -> Self {
        return SampleStruct {
            ip_address: address,
            port_number: port,
            sample_socket: Socket::new(
                if address.is_ipv4() { Domain::IPV4 } else { Domain:: IPV6 },
                Type::DGRAM,
                Some(Protocol::UDP)
            ).unwrap()
        }
    }
}

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 hoo = SampleStruct::new("127.0.0.1", 12345);
    println!("IP address = {}, Port = {}", hoo.ip_address.to_string(), hoo.port_number);

    let priv_ip: IpAddr = "192.168.0.1".parse::<IpAddr>().unwrap();
    let bar = SampleStruct::new(priv_ip, 12345);
    println!("IP address = {}, Port = {}", bar.ip_address.to_string(), bar.port_number);
}
```

実行結果

```
IP address = 127.0.0.1, Port = 12345
IP address = 127.0.0.1, Port = 12345
IP address = 192.168.0.1, Port = 12345
```

[Link to Rust Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=539c24bd97d72d99d51fd1b587613ef5)