3

我正在尝试实现基类和派生类的调用方法。但是,如果我做得正确,我会有点困惑。我想从基类设置值并在派生类中使用它们。

namespace Inheritance
{
    using System;

    public class BaseClass
    {
        public BaseClass() { }

        protected string methodName;
        protected int noOfTimes;
        public void Execute(string MethodName, int NoOfTimes)
        {
            this.methodName = MethodName;
            this.noOfTimes = NoOfTimes;
        }
    }

    public class DerivedClass : BaseClass
    {
        public DerivedClass() : base() { }

        public void Execute()
        {
            Console.WriteLine("Running {0}, {1} times", base.methodName, base.noOfTimes);
        }
    }

    public class Program
    {
        static void Main(string[] args)
        {
            DerivedClass d = new DerivedClass();
            d.Execute("Func", 2);
            d.Execute();

            Console.ReadLine();
        }
    }
}

问题:我可以只使用 1 次调用 Execute 而不是 2 次来实现与上述相同的效果吗?

我希望我上面的例子很清楚。如果不是这样,请告诉我,我将提供更多详细信息。

谢谢

4

4 回答 4

8

免责声明,我的回答假设您想要一个围绕方法继承及其实现的解决方案。提供的其他答案也是该问题的良好解决方案。

听起来您想覆盖派生类中的方法。为此,基类需要标记方法virtualabstract. 但是,在您的情况下,派生类方法签名是不同的。我会假设这是不理解它是如何工作的错误,所以我已经为你纠正了。

在这种情况下,派生类使用overrideC# 关键字标记方法。然后base.Execute(MethodName, NoOfTimes);,我想在重写的实现中使用基类的实现时调用。然后我输入我自己的代码。

base是另一个关键字,可让您访问您所在类的正下方的基类中的成员,而不会让继承链将您推回派生成员。

abstract值得一读,但在这种情况下不是必需的(它具有不同的行为,virtual但也与 结合使用override)。

namespace Inheritance
{
    using System;

    public class Program
    {
        internal protected class BaseClass
        {
            public BaseClass() { }

            protected string methodName;
            protected int noOfTimes;
            public virtual void Execute(string MethodName, int NoOfTimes)
            {
                this.methodName = MethodName;
                this.noOfTimes = NoOfTimes;
            }
        }

        internal class DerivedClass : BaseClass
        {
            public DerivedClass() : base() { }

            public override void Execute(string MethodName, int NoOfTimes)
            {
                base.Execute(MethodName, NoOfTimes);
                Console.WriteLine("Running {0}, {1} times", base.methodName, base.noOfTimes);
            }
        }

        static void Main(string[] args)
        {
            DerivedClass d = new DerivedClass();
            d.Execute("Func", 2);

            Console.ReadLine();
        }
    }
}

此示例有一些代码格式和命名怪癖,但我将不理会它,以尽可能接近您的原始代码。

于 2012-05-23T13:51:47.187 回答
4

这将是模板方法模式的理想候选者。基类没有重写 Execute,而是调用doWork必须由派生类提供的方法。这样,您就不会忘记调用base.Execute,并且可以在调用之前和之后在基类中做一些事情doWork

abstract class BaseClass 
{ 
    public BaseClass() { } 

    protected string methodName; 
    protected int noOfTimes; 
    public void Execute(string MethodName, int NoOfTimes) 
    { 
        this.methodName = MethodName; 
        this.noOfTimes = NoOfTimes;
        doWork();
    } 

    protected abstract void doWork(); // will be provided by derived classes
} 

class DerivedClass : BaseClass 
{ 
    public DerivedClass() : base() { } 

    protected override void doWork()
    {
        Console.WriteLine("Running {0}, {1} times", this.methodName, this.noOfTimes); 
    } 
} 

public class Program   
{   
    static void Main(string[] args) 
    { 
        DerivedClass d = new DerivedClass(); 
        d.Execute("Func", 2); 

        Console.ReadLine(); 
    } 
}

编辑:正如亚当在评论中正确指出的那样(谢谢),没有必要使基类抽象(如果您不需要实例化基类,这很方便,因为它会在以下情况下创建编译时错误子类不提供doWork) 的实现。或者,您可以在基类中指定默认行为:

class BaseClass 
{ 
    public BaseClass() { } 

    protected string methodName; 
    protected int noOfTimes; 
    public void Execute(string MethodName, int NoOfTimes) 
    { 
        this.methodName = MethodName; 
        this.noOfTimes = NoOfTimes;
        doWork();
    } 

    protected virtual void doWork() {
        // default behaviour, can be modified by subclasses
    }
} 
于 2012-05-23T13:57:14.593 回答
1

此外,在这种情况下,您不需要显式调用默认构造函数。

public DerivedClass() : base() { }

定义它就足够了

public DerivedClass() { }

基本构造函数将在派生构造函数之前自动调用。

至于我同意亚当的原始问题,他只是更快地完成了他的回答。:)

于 2012-05-23T13:55:44.750 回答
1

首先,在派生类中,您可以访问在基类中定义为公共或受保护的所有方法、变量和属性。这意味着不需要在派生类中使用 base.methodName。

base 用于(而不是通常隐含的 this)来访问在基类中定义的方法/属性的版本,而不是在派生类中重新定义它。这里不是这样。

此外,在您的情况下,您在基类和派生类中使用不同的签名(即参数的不同数量和/或类型)定义 Execute。这意味着您必须单独调用它们,因为它们是不同的。

仅当您在派生类中使用完全相同的参数定义版本时,您才能像 Adam 指出的那样使用 virtual 和 override,即使该版本没有使用它们。顺便说一句,在这里你使用 base 因为你想调用基类中定义的 Execute 版本。

于 2012-05-23T14:01:14.670 回答