什么时候应该将类成员声明为虚拟(C#)/可重写(VB.NET)?

时间:2020-03-05 18:58:15  来源:igfitidea点击:

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

解决方案

回答

如果要在基类中为其实现,则将其虚拟化,否则将其抽象化。

是的,只能将方法声明为虚拟方法。

回答

如果我们不想在基类中定义任何实现,并且希望强制在任何派生类中定义它,则可以使用abstract。如果要提供可以被派生类覆盖的默认实现,则将其定义为虚拟。

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

回答

抽象意味着我们不能提供默认的实现。反过来,这意味着所有子类都必须提供abstract方法的实现才能实例化(具体)。

我不确定我们所说的"限制"是什么意思,因此无法回答这一点。

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

回答

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

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

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

回答

首先,我将回答我们第二个问题。只能将方法声明为虚拟方法。
当我们想要基类中的某些默认功能时,可以选择虚拟而不是抽象,但是我们希望保留由继承自基类的类覆盖此功能的选项。
举些例子:

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

另一方面,如果实现Dog类,则在这种情况下可能想要实现Bark()方法,可能希望实现默认的吠叫声并将其放入Dog类中,而某些继承的类(如Chiwawa类可能希望重写此方法并实现特定的吠叫声。在这种情况下,树皮方法将被实现为虚拟方法,我们将能够实例化Dogs和Chiwawas。

回答

抽象方法或者属性(可以是虚拟的也可以是抽象的)只能在抽象类中声明并且不能具有主体,即我们不能在抽象类中实现它。

虚拟方法或者属性必须具有主体,即我们必须提供实现(即使主体为空)。

如果有人想使用抽象类,则他将必须实现一个继承自该类的类,并明确实现抽象方法和属性,但可以选择不覆盖虚拟方法和属性。

范例:

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");
        }
    }
}

回答

Windows窗体在这里有一个陷阱。

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

回答

我们所提出的问题更多与风格有关,而不是技术方面。我认为这本书
http://www.amazon.com/Framework-Design-Guidelines-Conventions-Development/dp/0321246756
围绕问题和许多其他问题进行了精彩的讨论。

回答

我亲自将大多数方法和属性标记为虚拟。我使用代理和大量延迟加载,因此我不必担心以后再进行更改。