北海 - Rust与面向对象(四)

本文探讨了JavaScript中的原型法如何在Rust中实现,以及Rust通过trait函数表与传统面向对象的差异,展示了如何利用原型法为`BytesMut`扩展功能。同时,文中还提及了装饰器模式在Rust中的挑战和迭代器模式的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原型法

此原型法非原型模式,而是类似JavaScript中的原型扩展,在JS中,能够很轻松地为String类型“原地”扩展方法,如:

String.prototype.isDigit = function() {
  return this.length && !(/\D/.test(this));
};

这个能力其实很好用,但是C++无法这样,一直觉得std::string的功能不足,想为其添加更丰富的如trim/split之类的语义,只能采用继承或者组合代理方式:

  • 继承:用一个新类继承std::string,并为新类实现trim/split

  • 组合代理:用一个新类组合std::string,并为新类代理所有std::string的方法,包括各类构造方法和析构方法,再为新类实现trim/split

然后,使用std::string的地方替换成新类。这时候那种都比较复杂,组合的方式更复杂一些,所以也别无脑相信面向对象里“组合一定优于继承”。幸运的是,Rust能轻易完成原型法,比如有个bytes库提供了可廉价共享的内存缓冲区,避免不必要的内存搬运拷贝,bytes::BytesMut实现了可变缓冲区bytes::BufMut,有一系列为其写入u8、i8、u16、i16、slice等基础类型的接口,对于基础的通用的在bytes库中已经足够了,现在有个网络模块,想往bytes::BytesMut中写入std::net::SocketAddr结构,Rust可轻易为BytesMut扩展实现put_socket_addr

pub trait WriteSocketAddr {
    fn put_socket_addr(&mut self, sock_addr: &std::net::SocketAddr);
}

impl WriteSocketAddr for bytes::BytesMut {
    fn put_socket_addr(&mut self, sock_addr: &std::net::SocketAddr) {
        match sock_addr {
            SocketAddr::V4(v4) => {
                self.put_u8(4);        // 代表v4地址族
                self.put_slice(v4.ip().octets().as_ref());
                self.put_u16(v4.port()); 
            }
            SocketAddr::V6(v6) => {
                self.put_u8(6);        // 代表v6地址族
                self.put_slice(v6.ip().octets().as_ref());
                self.put_u16(v6.port()); 
            }
        }
    }
}

然后就可以使用BytesMut::put_socket_addr了,只需use WriteSocketAddr引入这个trait就可以,是不是很轻松!为何会这么容易?先看JS的原型法,其背后是原型链在支撑,调用String的方法,不仅在Str

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值