A fluent interface is a design pattern that allows you to chain method calls together. In Godot, it is useful to create objects in a single line.
For example, suppose you wanted to create an item with a name, weight, and cost. This is how the script would look:
class_name Item extends Area3D
var name := ""
var weight := 1
var cost := 10
To use it in other script, in Godot, you would need to use new()
:
var item := Item.new()
func _ready() -> void:
item.name = "Sword"
item.weight = 2
item.cost = 20
This is a bit bothersome, because it splits the item definition in multiple places. You could make a constructor that takes all the parameters, like so:
class_name Item extends Area3D
var name := ""
var weight := 1
var cost := 10
func _init(p_name: String, p_weight: float, p_cost: int) -> void:
name = p_name
cost = p_cost
weight = p_weight
var item := Item.new("Sword", 2, 20)
But that makes it so you need to always pass arguments to Item
when you create it. This could be limiting; in the current example, there are only 3 properties, but in a real game, you might have many more.
One solution to this is custom constructors. Another is to use a fluent interface. Here's how you could implement it:
class_name Item extends Area3D
var name := ""
var weight := 1
var cost := 10
func setup(properties: Dictionary) -> Item:
for key in properties.keys():
if key in self:
self[key] = properties[key]
return self
Now you can create an item like this:
var item := Item.new().setup({
"name": "Sword",
"weight": 2,
"cost": 20
})
You can even chain more method calls together. For example, you could add an enchant()
method to the Item
class:
func enchant(enchantment: String) -> Item:
name = enchantment + " " + name
return self
var item := Item.new().setup({"name": "Sword"}).enchant("Magic")
See Also
Related terms in the Glossary