这是'模式'好的还是有更好的方法?

时间:2014-09-26 10:09:49

标签: c# oop derived-class derived-types

我的应用程序中有几个类(只是一个片段):

public abstract class Element {...}

public abstract class Program : Element
{
    ...

    public void SpecificProgramCall();
}

当我知道变量补丁属于子类型时,我使用:

((Program) element).SpecificProgramCall();

或更好:

var patch = patch as Program;
Debug.Assert(patch != null);
patch.SpecificProgramCall();

当我不知道它是否是一个程序时:

var patch = patch as (Program);
if (patch != null)
{
    patch.SpecificProgramCall();
}

但是,我的代码(将会)充满了这些结构。有没有更好的方法来实现这个?

示例:

var usedProgramBank = ((SetListSlot) setListSlot).UsedPatch.Parent as ProgramBank;
var key = new Tuple<ProgramBank, Program>(usedProgramBank, ((SetListSlot) setListSlot).UsedPatch as Program);
if (_dict.ContainsKey(key) && !_dict[key].Contains(setListSlot))
{
    _dict[key].Add(setListSlot);
}

2 个答案:

答案 0 :(得分:1)

这取决于您希望从代码中获得什么样的行为。如果将类Element中的SpecificProgramCall()方法声明为virtual,则可以在派生类中覆盖它。在基类中,您可以抛出错误或正常处理它。这可以简化对SpecificProgramCall调用的代码。

例如,如果SpecificProgramCall返回一个对象,那么在基类中你可以返回null并在派生类中返回一个对象。然后你要做的就是检查SpecificProgramCall的结果是否为空。

如果您正在使用多态,那么您的代码中必须存在问责制。你想把它放在哪里取决于你,最终取决于程序其余部分的结构。

答案 1 :(得分:1)

如果没有关于这些类型的更多具体信息(包括它们的语义,您对代码的访问等),我会说这种模式通常是动态调度的候选者。例如:

public abstract class Element
{
    public virtual void MaybeSpecificCall()
    {
        // nothing in most cases
    }
}

public abstract class Program : Element
{
    public override void MaybeSpecificCall()
    {
        base.MaybeSpecificCall();

        // but in this specific case, do something
        SpecificProgramCall(); 
    }

    public void SpecificProgramCall() { /* ... */ }
}

然后你可以在呼叫点做patch.MaybeSpecificCall(),让动态调度机制决定做某事而什么都不做。


或者,如果你不想搞乱基类,而你只是对没有看到“丑陋”的兴趣感兴趣。类型检查,然后帮助方法可以做到这一点:

static void IfProgram(this Element element, Action<Program> action)
{
    var program = element as Program;
    if(program != null) action.Invoke(program);
}

而且,再次,您使用patch.IfProgram(x => x.SpecificProgramCall())来调用它。我个人喜欢lambdas,但他们是否因为这份工作而感到丑陋取决于你。