开发文档内部
面向数据的接口
了解如何使用数据导向方法为接口提供字段功能
最后更新时间
作者:Idra
"面向数据的接口"听起来挺唬人,其实没那么复杂。简单来说,我们更倾向于用接口而不是类,因为接口支持多继承(当然还有其他原因,这里不展开)。但问题来了——接口不能有字段。
按传统思路,我们可能会这么写。假设要存方块朝向,像 RebarDirectionalBlock 那样:
interface RebarDirectionalBlock {
val facing
}这样就把问题甩给了实现方。但仔细想想,这很烦人——每个方块都得自己处理加载/保存逻辑(在 write 里写入方向,在加载构造函数里再读出来)。如果接口多了起来,会产生大量重复代码。
解决方案
我们的做法是用一个映射表来存每个 RebarDirectionalBlock 的朝向:
interface RebarDirectionalBlock {
var facing: BlockFace
get() = directionalBlocks[this] ?: error("No direction was set for block $key")
set(value) {
directionalBlocks[this] = value
}
companion object {
private val directionalBlocks = IdentityHashMap<RebarDirectionalBlock, BlockFace>()
}
}另外,还需要在方块序列化和反序列化时正确存取朝向:
@EventHandler
private fun onDeserialize(event: RebarBlockDeserializeEvent) {
val block = event.rebarBlock
if (block is RebarDirectionalBlock) {
directionalBlocks[block] = event.pdc.get(directionalBlockKey, RebarSerializers.BLOCK_FACE)
?: error("Direction not found for ${block.key}")
}
}
@EventHandler
private fun onSerialize(event: RebarBlockSerializeEvent) {
val block = event.rebarBlock
if (block is RebarDirectionalBlock) {
event.pdc.set(directionalBlockKey, RebarSerializers.BLOCK_FACE, directionalBlocks[block]!!)
}
}核心思路就是这样。