干净的代码:在缓存可变实例时防止意外行为

Clean code: preventing unexpected behavior when caching mutable instances

假设我有以下 2 类:

extends Resource
class_name MenuItem

export var food: Texture = preload("Burger.png")
export var drink: Texture = preload("Soda.png")

extends Node
class_name Meal

# "Public" variable
var menu_item: MenuItem setget _set_menu_item

# "Private" variables
onready var _food: Sprite = $Food
onready var _drink: Sprite = $Drink


func _set_menu_item(value: MenuItem) -> void:
    menu_item = value
    _food.texture = menu_item.food
    _drink.texture = menu_item.drink
    

问题是,如果我缓存 menu_item 属性:

,我会绕过修改器
extends Node

onready var meal: Meal = $Meal
onready var menu_item: MenuItem = meal.menu_item


func _ready() -> void:
    # Will trigger `_set_menu_item` and update `_food.texture`
    meal.menu_item.food = load("Salad.png")
    
    # Won't trigger `_set_menu_item` and won't update `_food.texture`
    menu_item.food = load("Soup.png")

在保持 类 可变的同时, 你如何确保 Meal 始终按预期运行并在 menu_item 时更新其精灵改变了吗?

我会使用自定义信号来做到这一点,我会从 MenuItem 的成员修改器发出并连接到更新私有 Meal 值的回调。

extends Resource
class_name MenuItem

# I use floating point "weight" instead of your Texture variables "food" and "drink"
# But everything should be same for Textures
export var weight: float = 0.0  setget _set_weight
signal weight_changed

func _set_weight(value: float) -> void:
    if weight != value:
        weight = value
        emit_signal("weight_changed")

extends Node
class_name Meal

# "Public" variable
var menu_item: MenuItem = MenuItem.new()

# "Private" variables
var _weigth: float = 0.0

func _ready():
    menu_item.connect("weight_changed", self, "_set_weight")

func _set_weight():
    _weigth = menu_item.weight

extends Node

onready var meal: Meal = $Meal
onready var menu_item: MenuItem = meal.menu_item

func _ready():
    # Will trigger `_set_weight` and update `_weight`
    meal.menu_item.weight = 2.0
    # Will do that also
    menu_item.weight = -2.0