首页 理论教育 使用Elixir显示角色和动作:函数式编程入门

使用Elixir显示角色和动作:函数式编程入门

时间:2023-11-20 理论教育 版权反馈
【摘要】:现在我们换一种方式解决这个问题,用多态函数处理DungeonCrawl.Character和DungeonCrawl.Room.Action。让我们在lib/dungeon_crawl/display.ex中创建协议:定义协议非常简单,只需要使用defprotocol指令。现在DungeonCrawl.Display协议有一个名为info/1的函数。现在,我们可以将DungeonCrawl.Display.info/1用于任何已实现的数据类型。让我们更新DungeonCrawl.CLI.BaseCommands:现在我们可以删除DungeonCrawl.CLI.HeroChoice和DungeonCrawl.CLI.RoomActionsChoice里使用Enum.map/2映射属性的部分:我们将数据直接传递给display_options/1。然后display_options/1将调用DungeonCrawl.Display.info/1显示信息。可以用Elixir的插值语法显示角色和动作吗?更新DungeonCrawl.CLI.BaseCommands.display_options/1,使用字符串插值:执行mix start,一切正常。

使用Elixir显示角色和动作:函数式编程入门

我们列出了玩家可选择的角色和房间动作,为此使用了两种结构体数据,DungeonCrawl.Character和DungeonCrawl.Room.Action。处理两种数据结构不容易,需要使用复杂的条件语句。我们的办法是在显示属性之前做映射,这是一个很好的解决方案。现在我们换一种方式解决这个问题,用多态函数处理DungeonCrawl.Character和DungeonCrawl.Room.Action。我们使用Elixir的协议创建多态函数。你将学习构建自己的协议和实现已有协议。

我们要创建一个函数,它既可以接收动作也可以接收角色。让我们在lib/dungeon_crawl/display.ex中创建协议:

定义协议非常简单,只需要使用defprotocol指令。然后用def创建一个函数,但不定义它的主体。现在DungeonCrawl.Display协议有一个名为info/1的函数。为了让它工作,还需要为我们的数据类型实现协议。再添加如下代码:

我们用指令defimpl实现协议,用for选项指定数据类型。在指令体内,我们实现了info/1函数。现在,我们可以将DungeonCrawl.Display.info/1用于任何已实现的数据类型。做这个扩展时,不需要修改数据模块。协议具有非常好的扩展性。让我们更新DungeonCrawl.CLI.BaseCommands:

现在我们可以删除DungeonCrawl.CLI.HeroChoice和DungeonCrawl.CLI.RoomActionsChoice里使用Enum.map/2映射属性的部分:

我们将数据直接传递给display_options/1。然后display_options/1将调用DungeonCrawl.Display.info/1显示信息。你可以执行mix start查看效果。

我们使用的DungeonCrawl.DungeonCrawl.Display.info/1有点冗长。可以用Elixir的插值语法显示角色和动作吗?例如,如果我们写"1 - #{character}",就能显示是角色名称,而不是整个结构体。Elixir的String.Chars协议可以做到。我们只需要实现to_string/1函数。让我们在模块DungeonCrawl.Character和DungeonCrawl.Room.Action中分别添加如下代码:(www.xing528.com)

这里不需要用for选项指定模块,因为我们正在模块内部实现协议。你可以删除DungeonCrawl.DungeonCrawl.Display协议,因为我们不再使用它了。更新DungeonCrawl.CLI.BaseCommands.display_options/1,使用字符串插值:

执行mix start,一切正常。Elixir的协议允许在接口代码不变的情况下添加新数据。如果你想了解更多有关协议及选项的信息,请查看官方文档。[4]

组织协议

协议代码的存放方式:如果你拥有结构体,请将实现代码放在定义结构体的文件里。如果你拥有协议,但不拥有结构体,请将该实现代码放在协议文件里。如果你既不拥有结构体,也不拥有协议,请使用协议名称创建一个文件并将实现代码放在那里。

本节先学习了引用结构体的结构体,以及代码的重构,然后学习了扩展已有的多态函数。然而,这还不够;协议适用于结构体,但不适用于简单的模块。下一节将学习为模块创建接口。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈