什么是像 Java 的 instanceof 这样的结构的函数?

Die*_*oAV 7 oop struct object instanceof rust

我正在用 Rust 制作一个 OOP 聊天客户端。模块 messages.rs 创建并处理发送到其他模块的消息作为 structs:SimpleMessageComplexMessagestructs:

//! # Messages

use time::SteadyTime;

/// Represents a simple text message
pub struct SimpleMessage<'a> {
    pub user: ...
    pub time: &'a SteadyTime<'a>,
    pub content: &'a str,
}

/// Represents attachments, like text or multimedia files.
pub struct ComplexMessage<'a> {
    pub user: ...
    pub time: &'a SteadyTime<'a>,
    //pub content: PENDING
}

impl<'a> SimpleMessage<'a> { }
impl<'a> ComplexMessage<'a> { }

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn is_simple() {
        assert_eq!(&self.instance_of(), SimpleMessage);
    }

    #[test]
    fn is_complex() {
        assert_eq!(&self.instance_of(), ComplexMessage);
    }
}
Run Code Online (Sandbox Code Playgroud)

我很难找到类似 Java 的函数,例如InstanceOf()结构体,它可能会像这样工作:

&self.instance_of() -> str
Run Code Online (Sandbox Code Playgroud)

这将用于处理ComplexMessage不同于SimpleMessageGUI 中的 ,为ComplexMessage.

有任何想法吗?

Pet*_*all 7

首先,如果您尝试将 Java OOP 习惯用法移植到 Rust,您将遇到困难。Rust 程序员使用完全不同的习语和模式,它们更适合语言的设计。

也就是说,您可以使用std::any::TypeId. 一个类似的功能,instanceOf可以实现这样的:

use std::any::{Any, TypeId};

trait InstanceOf
where
    Self: Any,
{
    fn instance_of<U: ?Sized + Any>(&self) -> bool {
        TypeId::of::<Self>() == TypeId::of::<U>()
    }
}

// implement this trait for every type that implements `Any` (which is most types)
impl<T: ?Sized + Any> InstanceOf for T {}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

let msg = ComplexMessage::new();

println!("msg is ComplexMessage: {}", msg.instance_of::<ComplexMessage>());
println!("msg is SimpleMessage: {}", msg.instance_of::<SimpleMessage>());
Run Code Online (Sandbox Code Playgroud)

输出:

use std::any::{Any, TypeId};

trait InstanceOf
where
    Self: Any,
{
    fn instance_of<U: ?Sized + Any>(&self) -> bool {
        TypeId::of::<Self>() == TypeId::of::<U>()
    }
}

// implement this trait for every type that implements `Any` (which is most types)
impl<T: ?Sized + Any> InstanceOf for T {}
Run Code Online (Sandbox Code Playgroud)

请注意,Rust 没有像 Java 那样的类型继承概念,因此这只会告诉您它是否完全相同的类型。


正如 DK 在此答案下面评论的那样,对您的问题更生疏的方法是使用 anenum来模拟您有两种消息的事实。Rust enums 与 Java enums 完全不同——它们与structs一样强大,只是它们模拟了替代的想法,而不是聚合。这是您可以使用您拥有的类型并将它们包装起来的一种方法:

enum Message<'a> {
    Complex(ComplexMessage<'a>),
    Simple(SimpleMessage<'a>),
}
Run Code Online (Sandbox Code Playgroud)

每当函数只能接受 a 时,ComplexMessage您可以编写签名来反映:

fn send_multimedia(msg: ComplexMessage) { ... }
Run Code Online (Sandbox Code Playgroud)

只要您可以接受任何一种类型,请使用enum

fn get_msg_size(msg: Message) -> usize {
    match(msg) {
        Message::Complex(complex) => complex.content.len() + complex.file.size(),
        Message::Simple(simple) => simple.content.len(),
    }
}
Run Code Online (Sandbox Code Playgroud)

  • [`Any::is`](https://doc.rust-lang.org/std/any/trait.Any.html#method.is) 不是更短的实现吗? (2认同)