应该何时将类成员声明为虚拟(C#)/ Overridable(VB.NET)?

时间:2008-09-17 08:15:59

标签: c# .net vb.net

为什么我不选择抽象?声明类成员虚拟有哪些限制?只能将方法声明为虚拟吗?

9 个答案:

答案 0 :(得分:10)

抽象方法或属性(都可以是虚拟的或抽象的)只能在抽象类中声明,并且不能有正文,即你不能在抽象类中实现它。

虚拟方法或属性必须具有正文,即您必须提供实现(即使正文为空)。

如果有人想要使用你的抽象类,他将不得不实现一个继承它的类并显式实现抽象方法和属性,但可以选择不覆盖虚方法和属性。

例如:

using System;
using C=System.Console;

namespace Foo
{
    public class Bar
    {
        public static void Main(string[] args)
        {
            myImplementationOfTest miot = new myImplementationOfTest();
            miot.myVirtualMethod();
            miot.myOtherVirtualMethod();
            miot.myProperty = 42;
            miot.myAbstractMethod();
        }
    }

    public abstract class test
    {
        public abstract int myProperty
        {
            get;
            set;
        }

        public abstract void myAbstractMethod();

        public virtual void myVirtualMethod()
        {
            C.WriteLine("foo");
        }

        public virtual void myOtherVirtualMethod()
        {
        }
    }

    public class myImplementationOfTest : test
    {
        private int _foo;
        public override int myProperty
        {
            get { return _foo; }
            set { _foo = value; }
        }

        public override void myAbstractMethod()
        {
            C.WriteLine(myProperty);
        }

        public override void myOtherVirtualMethod()
        {
            C.WriteLine("bar");
        }
    }
}

答案 1 :(得分:3)

如果您不想在基类中定义任何实现并希望强制在任何派生类中定义它,那么您将使用abstract。如果要提供可由派生类覆盖的默认实现,请将其定义为虚拟。

是的,只有方法可以是虚拟的。

答案 2 :(得分:2)

如果存在基本实现,则应将成员声明为虚拟成员,但可能会在子类中覆盖该功能。也可以使用Virtual而不是abstract来允许方法实现是可选的(即,基本实现是一个空方法)

将成员设置为虚拟时没有限制,但虚拟成员比非虚拟方法慢。

方法和属性都可以标记为虚拟。

答案 3 :(得分:1)

这里有一个需要注意Windows窗体的问题。

如果你想要一个可以继承的Control / UserControl,即使你在基类中没有逻辑,你也不希望它是抽象的,因为否则你将无法在派生中使用Designer类别: http://www.urbanpotato.net/default.aspx/document/2001

答案 4 :(得分:0)

如果你想在你的基类中给它一个实现,你就把它变成虚拟的,如果你不这样做,你就把它变成抽象的。

是的,只有方法可以声明为虚拟。

答案 5 :(得分:0)

摘要表示您无法提供默认实现。这反过来意味着所有子类必须提供抽象方法的实现才能实现(具体)。

我不确定你的'限制'是什么意思,所以无法回答这一点。

属性可以声明为虚拟,但您也可以在概念上将它们视为方法。

答案 6 :(得分:0)

首先,我将回答你的第二个问题。只有方法可以声明为虚拟。 当您需要基类中的某些默认功能时,可以选择虚拟而不是抽象,但是您希望保留通过从基类继承的类来覆盖此功能的选项。 例如:

如果要实现 Shape 类,则可能会有一个名为 getArea()的方法返回形状区域。在这种情况下,Shape类中的getArea()方法没有默认行为,因此您可以将其实现为 abstract 。将方法实现为抽象将阻止您实例化 Shape 对象。

另一方面,如果你实现了类 Dog ,你可能想要在这种情况下实现方法 Bark(),你可能想要实现默认值吠叫声并把它放在 Dog 类中,而一些继承的类,如类 Chiwawa 可能想要覆盖此方法并实现特定的吠叫声。在这种情况下,方法bark将实现为虚拟,您将能够实例化Dogs和Chiwawas。

答案 7 :(得分:0)

你的问题与风格有关,而不是技术问题。我认为这本书 http://www.amazon.com/Framework-Design-Guidelines-Conventions-Development/dp/0321246756 围绕你的问题和很多其他人进行了很好的讨论。

答案 8 :(得分:0)

我个人将大多数方法和属性标记为虚拟。我使用代理和延迟加载很多,所以我不想担心以后更改东西。