干净的代码:在缓存可变实例时防止意外行为 [英] Clean code: preventing unexpected behavior when caching mutable instances

查看:32
本文介绍了干净的代码:在缓存可变实例时防止意外行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有以下两个类:

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 属性,我会绕过 mutator:

The problem is that I bypass the mutator if I cache the menu_item property:

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 更改时更新其精灵?

While keeping both classes mutable, how would you ensure that Meal always behaves as expected and updates its sprites when menu_item is changed?

推荐答案

我会使用自定义信号来做到这一点,我将从 MenuItem 的成员 mutator 发出并连接到更新私人 Meal 的价值.

I would do that using custom signal, which I would emit from MenuItem's member mutator and connect to a callback that updates the private Meal's value.

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

这篇关于干净的代码:在缓存可变实例时防止意外行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆