何时调用base.method()以及base.method()中应该包含哪些代码?

时间:2009-06-26 14:01:20

标签: c# oop

在下面的示例中,派生类的编写者应该调用base.Add()。如果它发生在第一,基数可以做一种代码。如果它最后发生,基数可以做另一种逻辑(见样本)。我似乎不可能两种方式。简单的解决方法就是停止调用基本方法,因为基础永远不会知道它是被调用的第一个,最后一个还是中间或两个!

面向对象的方法是什么?我应该直接停止将代码放入基本方法中,因为我永远不会知道前后条件吗?

编辑:目标是拥有一个执行CRUD操作的业务对象类。重复的代码将被移动到基类。例如,检查是否在添加记录之前,业务对象的id为0并在保存后检查该业务对象的id是否为>。

namespace StackOverFlowSample
{
    class BusinessObjectBase
    {
        private bool _isNew;
        private int _id;
        public virtual void Add(string newAccount)
        {
            //Code that happens when subclasses run this method with the 
            //same signature

            //makes sense if base is called 1st
            if(_isNew && _id>0) throw new InvalidOperationException("Invalid precondition state");

            //makes sense if bae is called 2nd
            if (!_isNew && _id == 0) throw new InvalidOperationException("Invalid post condition state");
        }
    }
    class BusinessObject : BusinessObjectBase {
        public override void Add(string newAccount)
        {
            //doesn't make sense, because base will need to be called again.
            base.Add(newAccount);//pre validation, logging

            //Save newAccount to database

            //doesn't make sense, because base has already been called
            base.Add(newAccount);  //post validation, logging
        }
    }
}

3 个答案:

答案 0 :(得分:3)

如果您想要一种安全的方式来引入条件前和条件检查,您可以使Add非虚拟,而是使用派生类可以(或必须?)覆盖的另一种方法(AddInternal或类似的方法):

namespace StackOverFlowSample
{
    abstract class BusinessObjectBase
    {
        private bool _isNew;
        private int _id;

        protected abstract void AddInternal(string newAccount);
        public void Add(string newAccount)
        {
            if(_isNew && _id>0) throw new InvalidOperationException("Invalid precondition state");
            AddInternal(newAccount);    
            if (!_isNew && _id == 0) throw new InvalidOperationException("Invalid post condition state");
        }
    }
    class BusinessObject : BusinessObjectBase {
        protected override void AddInternal(string newAccount)
        {
            //Save newAccount to database
        }
    }
}

答案 1 :(得分:2)

很难按照你想要的方式遵循确切的例子,但是一个解决方案通常是使用模板模式 - 不要让子类调用基类,而是提供一个单独的抽象方法,它可以'做任何有用的事情除非它在基类中调用(非虚拟)方法 - 或者只返回模板方法可以用来调用真实方法的东西。

如果一切都是抽象的或密封的,我发现继承变得更容易理解 - 即你已经得到来覆盖它而你无法调用基本方法,或者你无法覆盖它开始。当然也有例外,但这是一个很好的起点。这也是一种看待事物的功能性方式 - 你可能会发现实际上没有继承,只需要让合适的代表提供专业化而不是......

答案 2 :(得分:1)

它是否有意义:

class BusinessObjectBase
{
    public void Add(string newAccount)
    {
        if(_isNew && _id>0) throw new InvalidOperationException("Invalid precondition state");

        AddOperation(newAccount);

        if (!_isNew && _id == 0) throw new InvalidOperationException("Invalid post condition state");
    }

    protected void virtual AddOperation(string newAccount)
    {
        // Code from base AddOperation
    }

}
class BusinessObject : BusinessObjectBase {
    protected override void AddOperation(string newAccount)
    {
        //custom AddOperation
    }
}