Java 的 instanceof 等结构的函数是什么?
What is a function for structs like Java's instanceof?
我正在用 Rust 制作一个 OOP 聊天客户端。模块 messages.rs 创建并处理发送给其他模块的消息作为结构:SimpleMessage
和 ComplexMessage
结构:
//! # 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()
,它可能会像:
&self.instance_of() -> str
这将用于处理与 GUI 中的 SimpleMessage
不同的 ComplexMessage
,为 ComplexMessage
添加预览和下载按钮。
有什么想法吗?
首先,如果您尝试将 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 {}
并像这样使用它:
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 那样的类型继承概念,所以这只会告诉您它是否是完全相同的类型。
正如 DK 在此答案下方评论的那样,解决您的问题的更 Rusty 方法是使用 enum
来模拟您有两种消息的事实。 Rust enum
s 与 Java enum
s 完全不同 - 它们与 struct
s 一样强大,除了它们模拟替代方案的想法,而不是聚合。这是您可以使用您拥有的类型并将它们包装起来实现它的一种方法:
enum Message<'a> {
Complex(ComplexMessage<'a>),
Simple(SimpleMessage<'a>),
}
每当一个函数只能接受一个 ComplexMessage
你可以写签名来反映:
fn send_multimedia(msg: ComplexMessage) { ... }
只要您可以接受任何一种类型,请使用 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(),
}
}
我正在用 Rust 制作一个 OOP 聊天客户端。模块 messages.rs 创建并处理发送给其他模块的消息作为结构:SimpleMessage
和 ComplexMessage
结构:
//! # 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()
,它可能会像:
&self.instance_of() -> str
这将用于处理与 GUI 中的 SimpleMessage
不同的 ComplexMessage
,为 ComplexMessage
添加预览和下载按钮。
有什么想法吗?
首先,如果您尝试将 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 {}
并像这样使用它:
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 那样的类型继承概念,所以这只会告诉您它是否是完全相同的类型。
正如 DK 在此答案下方评论的那样,解决您的问题的更 Rusty 方法是使用 enum
来模拟您有两种消息的事实。 Rust enum
s 与 Java enum
s 完全不同 - 它们与 struct
s 一样强大,除了它们模拟替代方案的想法,而不是聚合。这是您可以使用您拥有的类型并将它们包装起来实现它的一种方法:
enum Message<'a> {
Complex(ComplexMessage<'a>),
Simple(SimpleMessage<'a>),
}
每当一个函数只能接受一个 ComplexMessage
你可以写签名来反映:
fn send_multimedia(msg: ComplexMessage) { ... }
只要您可以接受任何一种类型,请使用 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(),
}
}