【发布时间】:2020-07-08 13:14:11
【问题描述】:
我正在努力解决如何安全地提出论点并确保处理所有可能性。
由于我有 Kotlin 背景,我正在用该语言编写示例:
package question
class StateA(val message: String)
class StateB(val number: Int)
object StateC
fun <State> render(state: State) = when (state) {
is StateA -> println("state is StateA, its message: ${state.message}")
is StateB -> println("state is StateB, its number: ${state.number}")
StateC -> println("state is StateC")
else -> println("Unknown type")
}
fun main() {
render(StateA("Hello world")) // prints: state is StateA, its message: Hello world
render(StateB(42)) // prints: state is StateB, its number: 42
render(StateC) // prints: state is StateC
render("Other type") // prints: Unknown type
}
when 语句检查泛型类型 State 并在类型匹配时进行安全强制转换,因此如果类型是 StateA,我可以访问 message,或者如果状态是,我可以访问 number StateB 的实例。
该代码有一个问题,即 else 分支,但我可以通过使用名为 sealed class 的语言功能来摆脱它,并且我在编译时知道所有可能的类型:
package question
import question.State.*
sealed class State {
class StateA(val message: String) : State()
class StateB(val number: Int) : State()
object StateC : State()
}
fun render(state: State) = when (state) {
is StateA -> println("state is StateA, its message: ${state.message}")
is StateB -> println("state is StateB, its number: ${state.number}")
StateC -> println("state is StateC")
}
fun main() {
render(StateA("Hello world")) // prints: state is StateA, its message: Hello world
render(StateB(42)) // prints: state is StateB, its number: 42
render(StateC) // prints: state is StateC
}
我在 Rust 中最接近的是使用 Any:
use std::any::Any;
struct StateA {
message: String,
}
struct StateB {
number: u8,
}
struct StateC {}
fn render(state: &dyn Any) {
if let Some(state_a) = state.downcast_ref::<StateA>() {
println!("state is StateA, its message: {}", state_a.message);
} else if let Some(state_b) = state.downcast_ref::<StateB>() {
println!("state is StateB, its number: {}", state_b.number);
} else if let Some(_) = state.downcast_ref::<StateC>() {
println!("state is StateC");
} else {
println!("Unknown type")
}
}
fn main() {
render(&StateA {
message: String::from("Hello World"),
}); // prints: state is StateA, its message: Hello World
render(&StateB { number: 42 }); // prints: state is StateB, its number: 42
render(&StateC {}); // prints: state is StateC
render(&"Other type"); // prints: Unknown type
}
这个解决方案与 Kotlin 中的第一个解决方案类似,所以它有相同的问题,else 分支
有没有办法在编译时知道所有可能的类型进行安全转换?类似于 Kotlin 的密封类解决方案,去掉 else 分支?
【问题讨论】:
-
为什么不使用an enum?
-
谢谢@Shepmaster,它工作得很好,我从没想过使用枚举,锈枚举比 kotlin/java 宇宙上的枚举更接近密封类。我会用工作代码添加答案,非常感谢!!