将类似方法移入通用实现

时间:2019-03-28 19:17:31

标签: c# unity3d generics

我正在尝试重构一些代码,不得不承认我对泛型的概念是陌生的。

我有一个基类:

BaseVarDef.cs:

using UnityEngine;
public abstract class BaseVarDef<T> : ScriptableObject
{
    [Multiline]
    public string DeveloperDescription = "";

    public T Value;

    public void SetValue(T value)
    {
        Value = value;
    }

}

然后,我从中派生了几个类。但是它们都包含我想重构为该通用基类的相同3种方法。唯一的区别是,他们期望当前正在定义它们的泛型类型或类。

FloatVar.cs

using UnityEngine;
[CreateAssetMenu(fileName = "New FloatVar", menuName = "Variables/FloatVar")]
public class FloatVar : BaseVarDef<float>
{
    public void SetValue(FloatVar value)
    {
        Value = value.Value;
    }
    public void ApplyChange(float amount)
    {
        Value += amount;
    }
    public void ApplyChange(FloatVar amount)
    {
        Value += amount.Value;
    }
}

StringVar.cs

using UnityEngine;
[CreateAssetMenu(fileName = "New StringVar", menuName = "Variables/StringVar")]
public class StringVar : BaseVarDef<string>
{
    public void SetValue(StringVar value)
    {
        Value = value.Value;
    }
    public void ApplyChange(string amount)
    {
        Value += amount;
    }
    public void ApplyChange(StringVar amount)
    {
        Value += amount.Value;
    }
}

是否可以将SetValue和2个重载的ApplyChange方法重构为BaseVarDef.cs?

预先感谢

2 个答案:

答案 0 :(得分:3)

我认为您可以在Base类中定义所有Apply和Set

public abstract class BaseVarDef<T>
{
    public string DeveloperDescription = "";

    public T Value;

    public void SetValue(T value)
    {
        Value = value;
    }
    public void SetValue(BaseVarDef<T> value)
    {
        Value = value.Value;
    }
    public void ApplyChange(T amount)
    {
        AddValue(amount);
    }
    public void ApplyChange(BaseVarDef<T> amount)
    {
        AddValue(amount.Value);
    }

    protected abstract void AddValue(T val);
}

public class FloatVar : BaseVarDef<float>
{
    protected override void AddValue(float val)
    {
        Value += val;
    }
}

答案 1 :(得分:1)

如果您可以仅将这些方法添加到原始基类中(然后从中删除abstract),则只需执行BaseVarDef<string>BaseVarDef<float>。不再需要FloatVarStringVar类!

这里最棘手的部分是+=运算符,该运算符不能应用于泛型(至少我没有意识到可以使您指定实现运算符的类型的约束)。

因此,您可以创建派生类必须按照Svetlana的描述实现的抽象Add方法,也可以如下所示使用dynamic(并完全不需要派生类)。

dynamic的一个问题是没有dynamic类型的编译时检查,因此它不是万无一失的。 类型T必须重载+运算符,否则您将获得运行时异常。您可以通过将行Value = amt + val;包装在{{1 }},但是您可能会得到意想不到的行为。

try/catch