什么是像 Java 的 instanceof 这样的结构的函数? [英] What is a function for structs like Java's instanceof?

查看:52
本文介绍了什么是像 Java 的 instanceof 这样的结构的函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm making an OOP chat client in Rust. The module messages.rs creates and handles messages to other modules as structs: SimpleMessage and ComplexMessage structs:

//! # 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);
    }
}

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

I'm troubled finding a Java-like function such as InstanceOf() for structs, that would potentially work like:

&self.instance_of() -> str

这将用于处理与 GUI 中的 SimpleMessage 不同的 ComplexMessage,为 ComplexMessage 添加预览和下载按钮.

This would be used to process a ComplexMessage different from a SimpleMessage in a GUI, adding a preview and download button for the ComplexMessage.

有什么想法吗?

推荐答案

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

First of all, if you try to port Java OOP idioms to Rust you are going to have a hard time. Rust programmers use completely different idioms and patterns, which are more suited to the design of the language.

也就是说,您可以使用 std::any::TypeId 比较类型.一个与 instanceOf 类似的函数可以这样实现:

That said, you can compare types using std::any::TypeId. A similar function to instanceOf can be implemented like this:

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 {}

像这样使用它:

let msg = ComplexMessage::new();

println!("msg is ComplexMessage: {}", msg.instance_of::<ComplexMessage>());
println!("msg is SimpleMessage: {}", msg.instance_of::<SimpleMessage>());

输出:

msg is ComplexMessage: true
msg is SimpleMessage: false

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

Note that Rust does not have a concept of type inheritance like Java does, so this will only tell you if it is exactly the same type.

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

A more Rusty approach to your problem, as DK commented below this answer, would be to use an enum to model the fact that you have two kinds of message. Rust enums are nothing like Java enums - they are just as powerful as structs except they model the idea of alternatives, as opposed to aggregates. Here is one way you could implement this using the types you have and wrapping them up:

enum Message<'a> {
    Complex(ComplexMessage<'a>),
    Simple(SimpleMessage<'a>),
}

当一个函数只能接受一个 ComplexMessage 时,你可以编写签名来反映这一点:

Whenever a function can only accept a ComplexMessage you can write the signature to reflect that:

fn send_multimedia(msg: ComplexMessage) { ... }

只要你可以接受任何一种类型,就使用 enum:

And whenever you can accept either type, use the 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(),
    }
}

这篇关于什么是像 Java 的 instanceof 这样的结构的函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆