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

时间:2023-01-15 16:51:44

Why wouldn't I choose abstract? What are the limitations to declaring a class member virtual? Can only methods be declared virtual?

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

9 个解决方案

#1


10  

An abstract method or property (both can be virtual or abstract) can only be declared in an abstract class and cannot have a body, i.e. you can't implement it in your abstract class.

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

A virtual method or property must have a body, i.e. you must provide an implementation (even if the body is empty).

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

If someone want to use your abstract class, he will have to implement a class that inherits from it and explicitly implement the abstract methods and properties but can chose to not override the virtual methods and properties.

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

Exemple :

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

#2


3  

You would use abstract if you do not want to define any implementation in the base class and want to force it to be defined in any derived classes. Define it as a virtual if you want to provide a default implementatio that can be overriden by derived classes.

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

Yes, only methods can be virtual.

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

#3


2  

A member should be declared virtual if there is a base implementation, but there is a possibility of that functionality being overridden in a child class. Virtual can also be used instead of abstract to allow a method implementation to be optional (ie. the base implementation is an empty method)

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

There is no limitation when setting a member as virtual, but virtual members are slower than non-virtual methods.

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

Both methods and properties can be marked as virtual.

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

#4


1  

There is a gotcha here to be aware of with Windows Forms.

Windows Forms需要注意这里的问题。

If you want a Control/UserControl from which you can inherit, even if you have no logic in the base class, you don't want it abstract, because otherwise you won't be able to use the Designer in the derived classes: http://www.urbanpotato.net/default.aspx/document/2001

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

#5


0  

If you want to give it an implementation in your base class you make it virtual, if you don't you make it abstract.

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

Yes, only methods can be declared virtual.

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

#6


0  

Abstract means that you can't provide a default implementation. This in turn means that all subclasses must provide an implementation of the abstract method in order to be instantiable (concrete).

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

I'm not sure what you mean by 'limitations', so can't answer that point.

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

Properties can be declared virtual, but you can conceptually think of them as methods too.

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

#7


0  

You question is more related to style than technicalities. I think that this book http://www.amazon.com/Framework-Design-Guidelines-Conventions-Development/dp/0321246756 has great discussion around your question and lots of others.

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

#8


0  

First of all, I will answer you second question. Only methods can be declared virtual. You would choose virtual instead of abstract when you want some default functionality in your base class, but you want to leave the option of overriding this functionality by classes that inherit from your base class. For examples:

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

If you are implementing the Shape class, you would probably have a method called getArea() that returns the area of your shape. In this case, there's no default behavior for the getArea() method in the Shape class, so you would implement it as abstract. Implementing a method as abstract will prevent you to instantiate a Shape object.

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

On the other hand, if you implement the class Dog, you may want to implement the method Bark() in this case, you may want to implement a default barking sound and put it in the Dog class, while some inherited classes, like the class Chiwawa may want to override this method and implement a specific barking sound. In this case, the method bark will be implemented as virtual and you will be able to instantiate Dogs as well as Chiwawas.

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

#9


0  

I personally mark most methods and properties virtual. I use proxies and lazy loading alot, so I don't want to have to worry about changing things at a later date.

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

#1


10  

An abstract method or property (both can be virtual or abstract) can only be declared in an abstract class and cannot have a body, i.e. you can't implement it in your abstract class.

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

A virtual method or property must have a body, i.e. you must provide an implementation (even if the body is empty).

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

If someone want to use your abstract class, he will have to implement a class that inherits from it and explicitly implement the abstract methods and properties but can chose to not override the virtual methods and properties.

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

Exemple :

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

#2


3  

You would use abstract if you do not want to define any implementation in the base class and want to force it to be defined in any derived classes. Define it as a virtual if you want to provide a default implementatio that can be overriden by derived classes.

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

Yes, only methods can be virtual.

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

#3


2  

A member should be declared virtual if there is a base implementation, but there is a possibility of that functionality being overridden in a child class. Virtual can also be used instead of abstract to allow a method implementation to be optional (ie. the base implementation is an empty method)

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

There is no limitation when setting a member as virtual, but virtual members are slower than non-virtual methods.

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

Both methods and properties can be marked as virtual.

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

#4


1  

There is a gotcha here to be aware of with Windows Forms.

Windows Forms需要注意这里的问题。

If you want a Control/UserControl from which you can inherit, even if you have no logic in the base class, you don't want it abstract, because otherwise you won't be able to use the Designer in the derived classes: http://www.urbanpotato.net/default.aspx/document/2001

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

#5


0  

If you want to give it an implementation in your base class you make it virtual, if you don't you make it abstract.

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

Yes, only methods can be declared virtual.

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

#6


0  

Abstract means that you can't provide a default implementation. This in turn means that all subclasses must provide an implementation of the abstract method in order to be instantiable (concrete).

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

I'm not sure what you mean by 'limitations', so can't answer that point.

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

Properties can be declared virtual, but you can conceptually think of them as methods too.

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

#7


0  

You question is more related to style than technicalities. I think that this book http://www.amazon.com/Framework-Design-Guidelines-Conventions-Development/dp/0321246756 has great discussion around your question and lots of others.

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

#8


0  

First of all, I will answer you second question. Only methods can be declared virtual. You would choose virtual instead of abstract when you want some default functionality in your base class, but you want to leave the option of overriding this functionality by classes that inherit from your base class. For examples:

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

If you are implementing the Shape class, you would probably have a method called getArea() that returns the area of your shape. In this case, there's no default behavior for the getArea() method in the Shape class, so you would implement it as abstract. Implementing a method as abstract will prevent you to instantiate a Shape object.

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

On the other hand, if you implement the class Dog, you may want to implement the method Bark() in this case, you may want to implement a default barking sound and put it in the Dog class, while some inherited classes, like the class Chiwawa may want to override this method and implement a specific barking sound. In this case, the method bark will be implemented as virtual and you will be able to instantiate Dogs as well as Chiwawas.

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

#9


0  

I personally mark most methods and properties virtual. I use proxies and lazy loading alot, so I don't want to have to worry about changing things at a later date.

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