0

如果这不符合规则,我很抱歉。但我认为这个问题需要一些解释,因为我自己不知道如何描述我什至是如何解决这个问题的。(TL;底部的 DR)

问题简介:

假设一个人正在使用各种形式的灯光。这些灯不一定共享相同的状态(亮度、色温……)。它们也可能没有相同数量的完整状态集。

例如,一个基本灯可能只有亮度,即一组状态,并且该组仅包含亮度。但是也可能有一个大灯,上面有4个聚光灯,可以分别控制亮度和色温。这 4 个聚光灯连接到一个对象,并且共享一些属性(名称、全局切换、对连接到设备的传感器的访问,...)

如果现在想使用冻结的类,可以将它们实现为 4 个不同的灯,但我希望它们位于单个实体下。所以假设 Lights 现在是“物理”实体,而 LightState 是可以在它们上更改的。

基本型号:

我们可以对它们进行如下建模;

@freezed
class LightState with _$LightState  {
   const factory LightState.default(Brightness brightness) = DefaultLightState;
   const factory LightState.colorTemperature(Brightness brightness, 
                                             ColorTemperature colorTemperature
                                             ) = ColorTemperatureLightState;
}

@freezed
class Light with _$Light {
   const factory Light.basic(LightState state) = BasicLight;
   const factory Light.massiveSpotlight(LightState state,
                                        LightState state2,
                                        LightState state3,
                                        LightState state4) = MassiveSpotlight;
}

与此类似的东西将在整个应用程序中运行良好。他们甚至共享他们的第一个“状态”,这意味着 light.state 在所有对象上都是可能的。

问题:

LightState 本身就是一个联合体,它包含几个不同的属性集合,而灯光应该只有一个这样的集合!因此,我们可能会跳到一个解决方案,而不是使用 LightState,例如:

@freezed
class Light with _$Light {
   const factory Light.basic(DefaultLightState state) = BasicLight;
   const factory Light.massiveSpotlight(ColorTemperatureLightState state,
                                        ColorTemperatureLightState state2,
                                        ColorTemperatureLightState state3,
                                        ColorTemperatureLightState state4) = MassiveSpotlight;
}

现在,这将实现介绍中提到的两种灯,并且效果很好,除了我需要的一件事:深度复制的较短版本!

MassiveSpotlight light; #suppose this was a valid instance with values

light.copyWith(
   state: light.state.copyWith(
         brightness: Brightness(100)
   )
);

这行得通。

MassiveSpotlight light; #suppose this was a valid instance with values

light.copyWith.state(brightness: Brightness(100)));

这没有。

CopyWith 根本不显示“状态”,这可能是因为“ColorTemperatureLightState”在技术上是一个抽象类,我猜这些根本没有相同的功能。

我为什么在乎?为什么不以不同的方式解决它?

好吧,对于我想保持冻结状态的人来说,地图功能之类的东西真的很好用。我不能不小心错过一些光的表现,因为它强加给我。它还有助于将更新分成多个流,因为并非所有实体都以相同的方式与应用程序通信。

使用带有继承的分层方法也有其自身的问题。例如,我想避免对 UI 层中的实体进行函数调用,而是希望将更改过程保留给应用程序层或简单地传递更改后的副本。

问题

有没有一种干净的方法来解决这个问题?

例如,是否有不同的方法将联合的特定类型用作另一个构造函数的参数,从而使 copyWith 保持不变?

我也对完全不同的解决方案的提议持开放态度。如果我不得不为这些课程扔掉冰冻的东西,我会的。如上所述,我目前不知道基于 UI 层中的输入更改应用程序层中的对象的干净方法 - 没有 - 基本上将功能映射到 UI。

因此,继续使用轻量级示例,我想避免在 UI 中调用诸如“setBrightness”、“turnOn/toggle”之类的设置器。但是我必须一次更改许多不同的属性。

TL;DR:我想在某个冻结类的构造函数中使用特定类型的冻结联合作为参数。然而,这破坏了 deep copyWith 的缩短版本。

4

0 回答 0